Segmentation Fault when using free()

L

lancer6238

Hi,

I keep getting segmentation fault when I try to free a particular
array variable.

"state" is defined as a 4-byte data type, and "NextState" is a global
variable. The value of state_size is 116994. Here is a portion of the
relevant code:

state **NextState = NULL; // in the main program file

/* In another file #include'd in the main program file */
static void Read(int *state_size)
{
...
NextState = (state **)malloc(sizeof(state*)*(*state_size));
for (i = 0 ; i < *state_size ; i++)
NextState = (state *)malloc(sizeof(state)*(258));
...
}

void FreeV(int state_size)
{
...
for (i = 0 ; i < state_size ; i++)
{
printf("%d %p %d\n", i, NextState, NextState); // For
checking purposes
free(NextState);
}
free(NextState);
}

Everytime I get to NextState[63], I get a segmentation fault. I've
check that the pointer to NextState[63] in FreeV() points to the same
address of NextState[63] created in Read(), and the value in NextState
is valid.

So why do I still get the segmentation fault at that particular point?

Thank you.
 
L

lancer6238

I keep getting segmentation fault when I try to free a particular
array variable.
"state" is defined as a 4-byte data type, and "NextState" is a global
variable. The value of state_size is 116994. Here is a portion of the
relevant code:

If you are referencing NextState, state_size is 116994, i,
ranges from 0 to 116993, and you only allocate 258 elements for the
second subscript, isn't that an out-of-range array access when i >
257?


That was an oversight on my part. I've changed that line arbitrarily
to NextState[67].
You are attempting to allocate 116994*258*sizeof(state) bytes of memory.
Assuming for the moment that sizeof(state) = 4, that is 120 megabytes
of memory. It would be worthwhile to check if all of the malloc()s
succeeded. Things like ulimit may cause problems *even if* "but I've
got a terabyte of swap space".

I've added

if(NextState == NULL)
{
printf("Error\n");
exit(0);
}

and

if (NextState == NULL)
{
printf("Error\n");
exit(0);
}

checks everytime I malloc the relevant memory, and did not see any
error messages.
It is quite possible to get a segmentation fault *inside* free() if
the data used by malloc() is corrupted, which can happen by, among
other things:

(1) Using more memory than you actually allocated (subscript or pointer
runs off the end or before the beginning). If you initialized
NextState[258][258], that could be stomping malloc()'s data.
(2) Freeing the same block twice
(3) Freeing auto or static storage
(4) Writing indirectly through uninitialized pointers.
(5) Some systems don't actually allocate memory until you try to *USE* it,
then give you a segmentation fault when it turns out you don't have that
much.

You can also get a segmentation fault in evaluting args for printf()
should some of the malloc() calls return NULL.

You haven't shown the code which might do (1) or (4).
I don't see instances of (2) or (3) in the code you show.

For (1), I've checked that the second subscript doesn't exceed 258.
For (2), I only free the NextState variables in the FreeV() function.
For (3), all NextState variables are dynamically allocated.
For (4), I can't find any instances of that.

The program runs fine if I comment out the free(NextState) line,
and the segmentation fault always occurs right before freeing NextState
[63]. I tried with another input file, and this time, the segmentation
fault always occurs before NextState[118]. In this instance, there are
a total of 1961 states.
state **NextState = NULL; // in the main program file
/* In another file #include'd in the main program file */
static void Read(int *state_size)
{
...
NextState = (state **)malloc(sizeof(state*)*(*state_size));
for (i = 0 ; i < *state_size ; i++)
NextState = (state *)malloc(sizeof(state)*(258));
...
}

void FreeV(int state_size)
{
...
for (i = 0 ; i < state_size ; i++)
{
printf("%d %p %d\n", i, NextState, NextState); // For
checking purposes
free(NextState);
}
free(NextState);
}

Everytime I get to NextState[63], I get a segmentation fault. I've
check that the pointer to NextState[63] in FreeV() points to the same
address of NextState[63] created in Read(), and the value in NextState
is valid.

So why do I still get the segmentation fault at that particular point?
 
F

Flash Gordon

On Jun 4, 11:05 am, (e-mail address removed) (Gordon Burditt) wrote:
It is quite possible to get a segmentation fault *inside* free() if
the data used by malloc() is corrupted, which can happen by, among
other things:

(1) Using more memory than you actually allocated (subscript or pointer
runs off the end or before the beginning). If you initialized
NextState[258][258], that could be stomping malloc()'s data.
(2) Freeing the same block twice
(3) Freeing auto or static storage
(4) Writing indirectly through uninitialized pointers.
(5) Some systems don't actually allocate memory until you try to *USE* it,
then give you a segmentation fault when it turns out you don't have that
much.

You can also get a segmentation fault in evaluting args for printf()
should some of the malloc() calls return NULL.

You haven't shown the code which might do (1) or (4).
I don't see instances of (2) or (3) in the code you show.

For (1), I've checked that the second subscript doesn't exceed 258.
For (2), I only free the NextState variables in the FreeV() function.
For (3), all NextState variables are dynamically allocated.
For (4), I can't find any instances of that.

The program runs fine if I comment out the free(NextState) line,
and the segmentation fault always occurs right before freeing NextState
[63]. I tried with another input file, and this time, the segmentation
fault always occurs before NextState[118]. In this instance, there are
a total of 1961 states.


You've corrupted something. You might not have managed to see the error,
but it is there. It might be overwriting the end of some *other*
malloc'd block..

If you are using Linux you might find valgrind useful.
state **NextState = NULL; // in the main program file
/* In another file #include'd in the main program file */
static void Read(int *state_size)
{
...
NextState = (state **)malloc(sizeof(state*)*(*state_size));
for (i = 0 ; i < *state_size ; i++)
NextState = (state *)malloc(sizeof(state)*(258));


On a side note, in C you don't need the casts, and there is a cleaner
(in my opinion) way to use sizeof...
NextState = malloc(*state_size * sizeof *NextState);
...
NextState = malloc(258 * sizeof *NextState);

I think this makes it easier to read and harder to get wrong!

<snip>
 
L

lancer6238

On Jun 4, 11:05 am, (e-mail address removed) (Gordon Burditt) wrote:
<snip>


It is quite possible to get a segmentation fault *inside* free() if
the data used by malloc() is corrupted, which can happen by, among
other things:
(1) Using more memory than you actually allocated (subscript or pointer
runs off the end or before the beginning). If you initialized
NextState[258][258], that could be stomping malloc()'s data.
(2) Freeing the same block twice
(3) Freeing auto or static storage
(4) Writing indirectly through uninitialized pointers.
(5) Some systems don't actually allocate memory until you try to *USE* it,
then give you a segmentation fault when it turns out you don't have that
much.
You can also get a segmentation fault in evaluting args for printf()
should some of the malloc() calls return NULL.
You haven't shown the code which might do (1) or (4).
I don't see instances of (2) or (3) in the code you show.
For (1), I've checked that the second subscript doesn't exceed 258.
For (2), I only free the NextState variables in the FreeV() function.
For (3), all NextState variables are dynamically allocated.
For (4), I can't find any instances of that.
The program runs fine if I comment out the free(NextState) line,
and the segmentation fault always occurs right before freeing NextState
[63]. I tried with another input file, and this time, the segmentation
fault always occurs before NextState[118]. In this instance, there are
a total of 1961 states.


You've corrupted something. You might not have managed to see the error,
but it is there. It might be overwriting the end of some *other*
malloc'd block..

If you are using Linux you might find valgrind useful.


Thanks for the recommendation to use Valgrind! I just found out that I
needed to allocate one more byte for my string variables, and that has
nothing to do with the NextState variables, which I thought was the
problem.
state **NextState = NULL; // in the main program file
/* In another file #include'd in the main program file */
static void Read(int *state_size)
{
...
NextState = (state **)malloc(sizeof(state*)*(*state_size));
for (i = 0 ; i < *state_size ; i++)
NextState = (state *)malloc(sizeof(state)*(258));


On a side note, in C you don't need the casts, and there is a cleaner
(in my opinion) way to use sizeof...
NextState = malloc(*state_size * sizeof *NextState);
...
NextState = malloc(258 * sizeof *NextState);

I think this makes it easier to read and harder to get wrong!

<snip>
 
D

Default User

Thanks for the recommendation to use Valgrind! I just found out that I
needed to allocate one more byte for my string variables, and that has
nothing to do with the NextState variables, which I thought was the
problem.

This is why the usual recommendation is to post a complete, minimal
program that demonstrates the problem. This is especially true when
dealing with memory corruption, where the problem is often not where it
seems.

Often cutting the program down to that "minimal" requirement will
isolate the portion of the code. If not, then at least the people here
are confident that they have the full picture, and can compile and run
the code as needed.




Brian
 
R

Richard Bos

Richard said:
Or run the damn thing in a debugger and catch the line that segs.

Congratulations. You have just discovered that the line that segs
contains a call to free(). Now feel free to use your debugger to find
out where the malloc arena gets clobbered - _or_ learn to read code.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top