Segmentation Fault ERROR in C

Hello guys, i have this code:

int main(int argc, char *argv[]) {
  int i, j, N, result = 0, **vec;

  if (argc < 2) {
    fprintf(stderr, "Usage: %s N\n", argv[0]);

  }

  /* ... how many numbers to read */
  N = atoi(argv[1]);
  /* check if N is a power of two; exit if not */
  if (! check(N)) {
    fprintf(stderr, "%d is not a power of 2 as required.  Exiting.\n", N);
    exit(1);
  }

  vec = (int**)malloc( (N)*(N)*sizeof(int*) );
  if ( vec == NULL ) {
    fprintf (stderr, "ERROR: not enough memory available!\n");
    exit ( 2 );
  }

  for (i = 0; i < N; i++)
    for (j = 0; j < N; j++)
      scanf("%d", &vec[j]);

  printf("\nOriginal array:\n ");
  for (i = 0; i < N; i++) {
    for (j = 0; j < N; j++)
      printf("%d ", vec[j]);
    printf("\n");
  }

  /* Now process array; example below is to add numbers */
  for (i = 0; i < N; i++) {
    result = check_property(vec, 0, N-1);
    printf("result[line %d]: %d\n", i, result);
  }

  /* free memory */
  free(vec);

  exit(0);

Basically i have to run it has eg. ./program N
my N needs to be a power of 2, like 4 or 8, 16 etc...
when i run it, it goes to the part of scanf and then if i write a number or file name, it gives me a segmentation fault error. Any ideas why?
I dont know if it is because of the memory allocation...

(There are functions there which i have defined but not illustrated, because they are not the problem i think)

The code:

  vet = (int**)malloc( (N)*(N)*sizeof(int*) );

allocates space for n**2 pointers to integers.

The code:

  for (i = 0; i < N; i++)
    for (j = 0; j < N; j++)
      scanf("%d", &vec[j]);

Tries to store N**2 integers (not pointers to integers) into a doubly dimensioned array, but the compiler has never been told the dimensions of that array. So, that can't work.

It looks like your code might be trying to set up an array of N pointers with each pointer pointing to a vector of N integers. But without seeing the code that defines check_property() , I'm obviously just guessing. Assuming that the 1st argument to that function is supposed to be a pointer to an array of N integers (not an array of pointers to integers), the following modification of your program might give you something you can use as a starting point:

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

char *IAm;

/* For this demo we dn't care about the argument being a power of 2; just > 0 */
int check(int N) {
	return(N > 0);
}

/* Calculate subscript into a vector for a simulated NxN array. */
int s(int N, int row, int col) {
	if(N < 0 || row < 0 || col < 0 || row >= N || col >= N) {
		fprintf(stderr, "%s: s(N=%d,row=%d,col=%d)\n",
		    IAm, N, row, col);
		fprintf(stderr, "%s: s(): Expect N>0, 0<=row<N, 0<=col<N\n",
		    IAm);
		exit(4);
	}
	return(row * N + col);
}

int main(int argc, char *argv[]) {
	int	i,
		j,
		N,
		result = 0,
		*vec;		/* Note *vec; not **vec. */

	IAm = argv[0];
	if (argc < 2) {
		fprintf(stderr, "Usage: %s N\n", argv[0]);
		exit(1);
	}

	/* ... how many numbers to read */
	N = atoi(argv[1]);
	/* check if N is a power of two; exit if not */
	if (! check(N)) {
		fprintf(stderr,
		    "%d is not a power of 2 as required.  Exiting.\n", N);
		exit(2);
	}

	vec = (int*)malloc( (N)*(N)*sizeof(int) ); /* int**->int*; int*->int */
	if ( vec == NULL ) {
		fprintf (stderr, "ERROR: not enough memory available!\n");
		exit(3);
	}

	for (i = 0; i < N; i++)
		for (j = 0; j < N; j++)
			scanf("%d", &vec[s(N, i, j)]); /* [j]->[s(N,i,j)] */

	printf("\nOriginal array:\n");  /* Trailing space removed from format.*/
	for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++)
			printf("%d ", vec[s(N, i, j)]);
		printf("\n");
	}

/* Without knowing what check_property() does, I don't know if:
**	check_property(vec, 0, N-1)
** in the following just needs to be changed to:
**	check_property(&vec[i * N], 0, N-1)
** or if something much deeper needs to be done.
*/
	/* Now process array; example below is to add numbers */
//	for (i = 0; i < N; i++) {
//		result = check_property(vec, 0, N-1);
//		printf("result[line %d]: %d\n", i, result);
//	}

	/* free memory */
	free(vec);

	exit(0);
}

Obviously you need to replace the check() function in this code with your own check() function. And, obviously, you need to have something that pipes or redirects a file that contains N**2 strings representing integer values into this code. If you just invoke it as:

./program 16

your program will hang until you type in 256 integer values separated by whitespace characters and with at least the last integer value followed by a <newline>.

Note also that instead of using vec as a doubly dimensioned array when reading values into it and printing the value stored in it, it treats it as a singly dimensioned array and gives the function s() the dimensions of the array and the row and column values to get the offset in that array treated as though it were a doubly dimensioned array.

If you invoke it with:

echo 11 12 13 14 21 22 23 24 31 32 33 34 41 42 43 44 | ./program 4

it will produce the output:

Original array:
11 12 13 14 
21 22 23 24 
31 32 33 34 
41 42 43 44 
3 Likes

Thank you for your answer!

Here are my functions which weren't illustrated.

check_property

int check_property(int *vec, int iL, int iR) {
  int k, res, resl, resr;
  int iM = (iR - iL) / 2;

  if (iM == 0) {
    if (vec[iL] != vec[iR]) return(0);
    else return(1);
  }
  for (res = 1, k = 0; k < (iR-iL); k++) {
    if (vec[iL + k] != vec[iL + k + 1]) {
      res = 0;
      break;
    }
  }
  resl = check_property(vec, iL, iL + iM);
  resr = check_property(vec, iL + iM+1, iR);
  return(res+min(resl,resr));
}

check

int check(int N) {
  int K = 1;

  while (K < N) {
    K = K * 2;
    if (K == N)
      return(1);
  }
  return(0);
}

min

int min(int a, int b) {
  if (a < b) return (a);
  else return(b);
}

But i agree with your code, and it works, the s() functions works fine on
&vec[s\(N, i, j\)]

But i still cant understand why it doesnt works with just
&vec[i][j]

You say:

By inc the i an j, I'm giving the dimension of the array until it reaches its max which is N^2 or am I incorrect?

Is there a way to do it without using the s() function?

POST EDIT:

I have done a new solution, i came up with this on the memory allocation:

/* allocate memory, read in the array and print it */
  vec = (int**)malloc(N*sizeof(int*));
  if ( vec == NULL ) {
    fprintf (stderr, "ERROR: not enough memory available!\n");
    exit ( 2 );
  }
/*New allocation*/
  for (j=0; j<N; j++){
    vec[j]= (int*)malloc(N*sizeof(int));
      if ( vec[j] == NULL ) {
    fprintf (stderr, "ERROR: not enough memory available!\n");
    exit ( 4 );
    }
  }

Now i understand what you were telling me about the dimensions.
I have debated this with a friend of mine and he told me there were 2 solutions to my problem; this one of the memory allocation, or yours, creating a s() function like you did

Thank you for your time!

No! You are creating an array of N^2 pointers to pointers to ints. So you have to store pointers to ints in the elements of the 1st dimension of the array (but you were storing ints there; not pointers to ints). And since (in a 64-bit programming environment) ints and pointers to ints are not the same size, storing an int in an area reserved for a pointer to an int might or might not work, but referencing the items stored in rows in the array as ints in check_property() will not reference the spots in which you stored them with your scanf() calls where you stored them in an object of type pointer to pointer to int. But you die before you get there because dereferencing vec[0][0] in scanf("%d", &vec[j]) uses vec[0] as a pointer, but you haven't initialized vec[0] yet, so you get a memory fault. And, if that location was a random value that points to a valid address, after you store an int there with your first scanf() call, dereferencing &vec[0][1] on the next call to scanf() will use the integer that you scanned on the first call as a pointer (but you stored an int there). The likelihood that the integer read in the 1st scanf() is a valid pointer is fairly low, and if it does happen to be valid, the likelihood that the integer value you stored in vet[0][0] is actually the address in memory of vec[0][0] is EXTREMELY unlikely. And it gets worse and worse as you scan more integers into the pointers to integers allocated for vec[] .

So, if you want to use a doubly dimensioned array the following code tries to do what I think you were trying to do. Here are a few notes concerning the following code:

  1. If you want to use a doubly dimensioned array, you have to create a doubly dimensioned array. In other words, vec in your code needs to be allocated as an array of N pointers to arrays of integers and each element of vec[] needs to be allocated as a pointer to an array of N integers.
  2. I made several stylistic changes to fit my programming style.
  3. I replaced the min() function with a macro.
  4. I renamed the check() function PowerOf2() (and modified it to allow all non-negative integral powers of 2; not just positive integral powers of 2).
  5. I added lots of debugging statements (trying to make sense of your comments about the check_property() function).
#include <stdio.h>
#include <stdlib.h>

#define min(a, b)	(a < b ? a : b)

int check_property(int *row, int iL, int iR) {
	int	k, res, resl, resr;
	int	iM = (iR - iL) / 2;

	printf("check_property(%p, %d, %d) row[%d]=%d, row[%d]=%d\n",
	    row, iL, iR, iL, row[iL], iR, row[iR]);
	if (iM == 0) {
		printf("check_property(%p, %d, %d) returning %d\n",
		    row, iL, iR, row[iL] == row[iR]);
		return(row[iL] == row[iR]);
	}
	for (res = 1, k = 0; k < (iR-iL); k++) {
		if (row[iL + k] != row[iL + k + 1]) {
			res = 0;
			break;
		}
	}
	resl = check_property(row, iL, iL + iM);
	resr = check_property(row, iL + iM+1, iR);
	printf("check_property(%p, %d, %d) returning %d\n",
	    row, iL, iR, res + min(resl,resr));
	return(res+min(resl,resr));
}

/* Return 1 if N is a power of 2; otherwise, 0. */
/* Note that 1 is 2**0 and is a power of 2. */
int PowerOf2(int N) {
	int K = 1;
	while (K < N)
		/* Shift left one bit and multiply by 2 produce the same
		** results.
		*/
		K <<= 1;
	return(K == N);
}

int main(int argc, char *argv[]) {
	int	i,
		j,
		N,
		result = 0,
		**vec;

	if(argc < 2) {
		fprintf(stderr, "Usage: %s N\n", argv[0]);
		exit(1);
	}

	/* ... how many numbers to read */
	N = atoi(argv[1]);
	/* check if N is a power of two; exit if not */
	if(! PowerOf2(N)) {
		fprintf(stderr,
		    "%d is not a power of 2 as required.  Exiting.\n", N);
		exit(2);
	}

	/* Create array of N pointers to arrays of ints. */
	vet = (int**)malloc(N * sizeof(int*));
	if(vec == NULL) {
		fprintf (stderr, "ERROR: not enough memory available!\n");
		exit(3);
	}
	/* Now create N arrays of N ints. */
	for(i = 0; i < N; i++) {
		/* Note sizeof(int); not int* in following malloc(). */
		vec = (int*)malloc(N * sizeof(int));
		if(vec == NULL) {
			fprintf(stderr,
			    "ERROR: not enough memory available!\n");
			exit(3);
		}
	}

	for(i = 0; i < N; i++)
		for(j = 0; j < N; j++)
			scanf("%d", &vec[j]);

	printf("\nOriginal array:\n");  /* Trailing space removed from format.*/
	for(i = 0; i < N; i++) {
		for(j = 0; j < N; j++)
			printf("%d ", vec[j]);
		printf("\n");
	}

	/* Now process array; example below is to add numbers */
	/* Saying that check_property() adds numbers is not at all enlightening.
	** It seems to return 1 if all pairs of numbers on a row have the same
	** value (or if there is only one element on a row) and to return 0 if
	** one or more pairs of numbers on a row have different values.
	*/
	for(i = 0; i < N; i++) {
		printf("Processing row %d...\n", i);
		result = check_property(vec, 0, N-1);
		printf("result[row %d]: %d\n", i, result);
	}

	/* free memory */
	for(i = 0; i < N; i++)
		free(vec);
	free(vec);

	exit(0);
}
1 Like