Hi.

I have written a program to build an array and move values around until a point of "equilibrium" is reached. It then records how many of each number there are and outputs them to a file. My program works in part, but sometimes encounters a seg fault (I think I'm over running an array but can't see where).

I would appreciate if someone could find the source of this and any other problems with my program (anything at all!)

Here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main ( void )

{
	int i, j, k, **lattice = 0, row, col, sum = 0;
	int average, check, pcntlatt, table[15][2], startlim;
	
	FILE         *output;
	const char    out_fn[]="0604632_proj2.out";

	
	row = 5;
	col = 5;
	startlim = 5;
	
	lattice = malloc (row * sizeof(int *));
	srand ( (unsigned)time ( NULL ) );

	for(i = 0; i < row; i++)
	{
		lattice[i] = malloc(col * sizeof(int));
	}
	
	for(k = 0; k < (11); k++)
	{
		table[k][0] = k;
	}
	
	for(i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			lattice[i][j] = rand() / ( RAND_MAX / startlim + 1 );
		}
	}


	pcntlatt =  (3*row*col)/5;

	table[0][1] = 0;

	while (table[0][1] < pcntlatt)
	{

	table[0][1] = 0;
	table[1][1] = 0;
	table[2][1] = 0;
	table[3][1] = 0;
	table[4][1] = 0;
	table[5][1] = 0;
	table[6][1] = 0;
	table[7][1] = 0;
	table[8][1] = 0;
	table[9][1] = 0;
	table[10][1] = 0;
	table[11][1] = 0;
	table[12][1] = 0;
	table[13][1] = 0;
	table[14][1] = 0;
	table[15][1] = 0;

	i = rand() / (RAND_MAX / row);
	j = rand() / (RAND_MAX / col);

	
		if (lattice [i][j] != 0)
		{
	
			lattice[i][j] = (lattice [i][j])--;

			i = rand() / (RAND_MAX / row);
			j = rand() / (RAND_MAX / col);

			lattice[i][j] = (lattice [i][j])++;

		}

		for (i = 0; i < row; i++)
		{
			for (j = 0; j < col; j++)
			{
				
				switch (lattice[i][j])
				{
					case 0:
						table[0][1] = table[0][1]++;
						break;
					case 1:
						table[1][1] = table[1][1]++;
						break;
					case 2:
						table[2][1] = table[2][1]++;
						break;
					case 3:
						table[3][1] = table[3][1]++;
						break;
					case 4:
						table[4][1] = table[4][1]++;
						break;
					case 5:
						table[5][1] = table[5][1]++;
						break;
					case 6:
						table[6][1] = table[6][1]++;
						break;
					case 7:
						table[7][1] = table[7][1]++;
						break;
					case 8:
						table[8][1] = table[8][1]++;
						break;
					case 9:
						table[9][1] = table[9][1]++;
						break;
					case 10:
						table[10][1] = table[10][1]++;
						break;						
					case 11:
						table[11][1] = table[11][1]++;
						break;						
					case 12:
						table[12][1] = table[12][1]++;
						break;						
					case 13:
							table[13][1] = table[13][1]++;
						break;						
					case 14:
						table[14][1] = table[14][1]++;
						break;						
					case 15:
						table[15][1] = table[15][1]++;
						break;
					default:
						break;	
				}
			}
		}
	}
	
	output = fopen ("0604632_proj2.out", "w");
	
	for (k = 0; k < (11); k++)
	{
		printf("%d %d\n", table[k][0], table[k][1]);
		fprintf(output, "%d %d\n", table[k][0], table[k][1]);
	}
	fclose(output);
	
return (0);
}

>(I think I'm over running an array but can't see where).

table[15][1] = 0;

To start, table can only be indexed to 14

>(anything at all!)
There's not guarantee that malloc will allocate memory. You MUST check the return of that call.
Where do you free the malloc()ed memory that you set apart?

malloc not freed and Array overflow errors as indicated by Aia should be checked and the error over flow in line no 64 causes error in every compilation and hence comes in notice.

But the same Array overflow error in Line 135 comes over only in certain cases and hence ought to be considered.

Ok I have made some changes, but still getting a seg fault in the while loop. Can't see why just yet.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main ( void )

{
	int i, j, k, **lattice = 0, row, col, sum = 0;
	int average, check, pcntlatt, table[16][2], startlim;
	
	FILE         *output;
	const char    out_fn[]="0604632_proj2.out";

	printf ("Test 1 passed\n");
	
	row = 5;
	col = 5;
	startlim = 5;
	
	lattice = malloc (row * sizeof(int *));
	srand ( (unsigned)time ( NULL ) );
	
	printf ("Test 2 passed\n");
	
	for(i = 0; i < row; i++)
	{
		lattice[i] = malloc(col * sizeof(int));
	}
	
	printf ("Test 3 passed\n");
	
	if (lattice == NULL)
	{
		printf ("Out of Memory\n");
		fprintf(output, "Out of Memory\n");
		exit(0);
	}
	
	printf ("Test 4 passed\n");
	
	for(k = 0; k < (16); k++)
	{
		table[k][0] = k;
	}
	
	printf ("Test 5 passed\n");
	
	for(i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			lattice[i][j] = rand() / ( RAND_MAX / startlim + 1 );
		}
	}

	printf ("Test 6 passed\n");

	pcntlatt =  (3*row*col)/5;

	table[0][1] = 0;

	while (table[0][1] < pcntlatt)
	{
		for (k = 0; k < 16; k++)
		{
			table[k][1] = 0;
		}
		
		printf ("Test 7 passed\n");
		
		i = rand() / (RAND_MAX / row);
		j = rand() / (RAND_MAX / col);

	
		if (lattice [i][j] != 0)
		{
	
			lattice[i][j] = (lattice [i][j])--;

			i = rand() / (RAND_MAX / row);
			j = rand() / (RAND_MAX / col);

			lattice[i][j] = (lattice [i][j])++;

		}

		printf ("Test 8 passed\n");

		for (i = 0; i < row; i++)
		{
			for (j = 0; j < col; j++)
			{
				
				switch (lattice[i][j])
				{
					case 0:
						table[0][1] = table[0][1]++;
						break;
					case 1:
						table[1][1] = table[1][1]++;
						break;
					case 2:
						table[2][1] = table[2][1]++;
						break;
					case 3:
						table[3][1] = table[3][1]++;
						break;
					case 4:
						table[4][1] = table[4][1]++;
						break;
					case 5:
						table[5][1] = table[5][1]++;
						break;
					case 6:
						table[6][1] = table[6][1]++;
						break;
					case 7:
						table[7][1] = table[7][1]++;
						break;
					case 8:
						table[8][1] = table[8][1]++;
						break;
					case 9:
						table[9][1] = table[9][1]++;
						break;
					case 10:
						table[10][1] = table[10][1]++;
						break;						
					case 11:
						table[11][1] = table[11][1]++;
						break;						
					case 12:
						table[12][1] = table[12][1]++;
						break;						
					case 13:
						table[13][1] = table[13][1]++;
						break;						
					case 14:
						table[14][1] = table[14][1]++;
						break;						
					case 15:
						table[15][1] = table[15][1]++;
						break;
					default:
						break;	
				}
			}
		}
	}
	
	printf ("Test 9 passed\n");
	
	output = fopen ("0604632_proj2.out", "w");
	
	for (k = 0; k < (16); k++)
	{
		printf("%d %d\n", table[k][0], table[k][1]);
		fprintf(output, "%d %d\n", table[k][0], table[k][1]);
	}
	fclose(output);
	
	printf ("Test 10 passed\n");
	
	free(lattice);
	lattice = NULL;
	
	printf ("All tests passed\n");
	
return (0);
}

Also is there anyway to both reduce the number of case statements and make so if I wanted to say, double the number of cases, I can add to it more quickly than making a huge list of cases? I was thinking something along the lines of a sort of general case of table [1] but I wasn't sure if that is even possible.

You can replace your entire switch statement with table[lattice[i][j]][1]++ .

By the way, you are using ++ and -- incorrectly. It is NOT a = a++ , but simply a++ .

As for the segfault, it may be because of the way you are using rand(). Try changing everywhere it says rand() / (RAND_MAX / max) to rand() % max .

Well as much as I have seen your switch is not doing any thing other than going to the case n where n=lattice[j] and doing
table[n][1]=table[n][1]++

And with this thing in mind if the sole purpose of your switch is what I have stated above then your whole switch statement can be substituted with just one statement.

table[lattice[j]][1]++

Line no 79 84 even though not wrong are not needed...
Just lattice[j]++ or -- is enough.

line 21 and 24:

lattice = malloc (row * sizeof(int *));

lattice[i] = malloc(col * sizeof(int));

I may be wrong but i feel the memory allocation of single * and double * pointers are not done properly.
Here lattice is actually **lattice and lattice is *lattice and are different.

csurfer: Do you always just repeat what other people have already said?

csurfer: Do you always just repeat what other people have already said?

I am sorry if you felt so but when i started replying to this thread your post was not there and deleting a post is not in my hand.

Sorry csurfer, I wasn't thinking.

Hey Guys.

I am still getting the segmentation fault and can't figure out how I'm doing malloc wrong

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main ( void )

{
	int i, j, k, **lattice = 0, row, col, sum = 0;
	int average, check, pcntlatt, table[16][2], startlim;
	
	FILE         *output;
	const char    out_fn[]="0604632_proj2.out";

	printf ("Test 1 passed\n");
	
	row = 5;
	col = 5;
	startlim = 5;
	
	lattice = malloc (row * sizeof(int *));
	srand ( (unsigned)time ( NULL ) );
	
	printf ("Test 2 passed\n");
	
	for(i = 0; i < row; i++)
	{
		lattice[i] = malloc(col * sizeof(int *));
	}
	
	printf ("Test 3 passed\n");
	
	if (lattice == NULL)
	{
		printf ("Out of Memory\n");
		fprintf(output, "Out of Memory\n");
		exit(0);
	}
	
	printf ("Test 4 passed\n");
	
	for(k = 0; k < (16); k++)
	{
		table[k][0] = k;
	}
	
	printf ("Test 5 passed\n");
	
	for(i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			lattice[i][j] = rand() / ( RAND_MAX / startlim + 1 );
		}
	}

	printf ("Test 6 passed\n");

	pcntlatt =  (3*row*col)/5;

	table[0][1] = 0;

	while (table[0][1] < pcntlatt)
	{
		for (k = 0; k < 16; k++)
		{
			table[k][1] = 0;
		}
		
		printf ("Test 7 passed\n");
		
		i = rand() / (RAND_MAX / row);
		j = rand() / (RAND_MAX / col);

	
		if (lattice [i][j] != 0)
		{
	
			(lattice [i][j])--;

			i = rand() / (RAND_MAX / row);
			j = rand() / (RAND_MAX / col);

			(lattice [i][j])++;

		}

		printf ("Test 8 passed\n");

		for (i = 0; i < row; i++)
		{
			for (j = 0; j < col; j++)
			{
				
				table[lattice[i][j]][1]++;
				
			}
		}
	}
	
	printf ("Test 9 passed\n");
	
	output = fopen ("0604632_proj2.out", "w");
	
	for (k = 0; k < (16); k++)
	{
		printf("%d %d\n", table[k][0], table[k][1]);
		fprintf(output, "%d %d\n", table[k][0], table[k][1]);
	}
	fclose(output);
	
	printf ("Test 10 passed\n");
	
	free(lattice);
	lattice = NULL;
	
	printf ("All tests passed\n");
	
return (0);
}

I assume you expect this idiom to give a number between 0 and row - 1: rand() / (RAND_MAX / row) But in fact it occasionally gives a value of row. This is because RAND_MAX is not evenly divisible by row (i.e., there's a little left over). Here's some empirical proof:

int n = 0, i;
    for (i = 0; i < 100000; i++)
        if (rand() / (RAND_MAX / 5) >= 5) n++;
    printf ("%d\n", n);

Instead change it in all similar places to this which can never be out of range: rand() % row

Also, your lattice values can be 16 or greater, so you get out of range errors accessing table with lattice. Try this to see the problem. (Replaces lines 90 to 98 in your previous listing.)

for (i = 0; i < row; i++)
    for (j = 0; j < col; j++)
        if (lattice[i][j] >= 16)
            printf ("%d\n", lattice[i][j]);
        else
            table[lattice[i][j]][1]++;

That all works brilliantly. Thank you.

One more thing. I need to make the output file be in two columns, one labeled m(e) another labeled v, but I can't get the columns of the array to be separated in the output file, it just prints a string of characters. Any tips?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.