Mombu the Programming Forum sponsored links

Go Back   Mombu the Programming Forum > Programming > I want my segmentation fault!
User Name
Password
REGISTER NOW! Mark Forums Read

sponsored links


Reply
 
1 13th March 00:38
allan adler
External User
 
Posts: 1
Default I want my segmentation fault!



I don't have any experience with the free command and don't understand


structures and it eventually used up all memory and all swap space
before the OS killed it. So, now I'm going through it and trying to
fix all the leaks. The basic approach I'm taking is to list all the
routines I use that return pointers (I call them allocators) and
make sure that every routine that calls an allocator either returns
the pointer returned by the allocator (either directly or as a component
of something it does return or indirectly, by side effects) or else
calls another routine to free the pointer. I'm going through the list,
one allocator at a time, and grepping to find out every place it is
called and freeing what it returns when that is warranted.

This is not an unpleasant activity and, in the process, I'm finding lots
of functions that seemed like a good idea at the time but which in fact
are never called, and commenting them out. On the other hand, I don't
really know the effect that these efforts to free pointers are really
having. So, as an experiment, I wrote some sample code, included below,
intended to test the approach I'm taking. I ran it and I find it
inconclusive. First let me show you the code and then I'll explain what the problem is.
#include <stdio.h>
struct measured_list {
int length_of_list;
int * list_of_int;
};
struct measured_list * alloc_ml(int n, int * l)
{
int i;
struct measured_list *ml;
ml = (struct measured_list *) malloc(sizeof(struct measured_list));
ml->length_of_list = n;
ml->list_of_int = (int *) malloc(n*sizeof(int));
for(i=0;i<n;i++) ml->list_of_int[i] = l[i];
return ml;
}
void free_ml(struct measured_list **ml) { int i;
free((*ml)->list_of_int);
free(*ml);
return;
}
struct measured_list * copy_ml(struct measured_list * ml)
{
int i,n,*l; struct measured_list * new_ml;
n = ml->length_of_list;
l = ml->list_of_int;
new_ml = alloc_ml(n,l);
return new_ml;
}
int main() { int i,l[3]={2,3,7};
/* printf("ml1->list_of_int[0] = %d\n",ml1->list_of_int[0]); */
ml1 = alloc_ml(3,l);
ml2 = copy_alloc(ml1);
ml3 = copy_alloc(ml2); free_ml(&ml1); free_ml(&ml2); free_ml(&ml3);
printf("ml1->list_of_int[0] = %d\n",ml1->list_of_int[0]);
return 0;
}

If I uncomment the line containing the first printf statement, I get
a segmentation fault, because the array of three integers ml1->list_of_int
hasn't been allocated yet. That's what I'm used to. If the same thing
happened with the printf statement following free_ml(&ml3), I'd be
convinced that the space was really unallocated and available for
recycling. But instead, it prints out garbage. So, I'm unconvinced
and confused. If you can think of a better test of whether this
memory is really available for reuse, I'd be glad to know about it.

Hmmm, now that I think about it, another approach occurs to me:
I can write a for loop that keeps generating copies of ml1, like
the Sorcerer's Apprentice, and choose the number of iterations by
experiment until it is so large that the program gets killed after
using up all the memory and swap space. Then modify the loop so
that it frees the preceding copy with free_ml after it generates the
new one, and tell it to print out the last one, and see whether the
program still dies and whether I can make the number of iterations
even larger. I'll try that after I log out. Just in case it is the
wrong approach, or there is a better way, I'll still post this and
look forward to your comments.

Since this is a discussion group for C, and not one for Linux, I won't
tell you that I am doing this on a PC running RH 7.1 Linux. -- Ignorantly,
Allan Adler <ara@zurich.csail.mit.edu>
* Disclaimer: I am a guest and *not* a member of the MIT CSAIL. My actions and
* comments do not reflect in any way on MIT. Also, I am nowhere near Boston.
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote


  sponsored links


2 13th March 04:22
chrish
External User
 
Posts: 1
Default I want my segmentation fault!



....
I believe adding a line in free_ml (before return like:
*ml = NULL;

will get you the seg-fault

cheers
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote
3 13th March 08:11
willerz
External User
 
Posts: 1
Default I want my segmentation fault!


I suggest you use a tool like IBM Rational Purify. It can tell you how much
memory you have leaked and where you allocated that memory. If you aks
nicely it can also tell you if you ever read from storage which has never


which bits of your code are unused.

Some parts of academia can get Purify for free on the IBM Scholars Program
which was at http://ibm.com/university the last time I looked, but that was
over 3 years ago now.

There's also a free (gratis and libre) tool called Valgrind which I'm told
can do the some of the same things on Linux, but I never got the hang of
it.
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote
4 13th March 08:11
hans-bernhard broeker
External User
 
Posts: 1
Default I want my segmentation fault!


You're basing the invitation to let yourslef be convinced on incorrect
assumptions.

There is no such thing as a right to get a segfault. What your code
does is cause undefined behaviour. You can't expect undefined
behaviour to come in some particular flavour --- that's why it's
called "undefined".

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote
5 13th March 08:11
barry schwarz
External User
 
Posts: 1
Default I want my segmentation fault!


On 29 Sep 2006 08:35:37 GMT, Allan Adler <ara@nestle.csail.mit.edu>


Don't cast the return from malloc. Doing so caused the compiler to
suppress a diagnostic which would have alerted you to the fact the
your forgot to include stdlib.h. As it is coded now, it invokes
undefined behavior because a C89 compiler is required to erroneously
assume that malloc returns an int.

Where are ml1, ml2, and ml3 defined?

This invokes undefined behavior because ml1 has been freed.

No, you invoked undefined behavior because ml1 is not initialized.
Fortunately, the undefined behavior resulted in something that got your immediate attention.


Undefined behavior is not required to be convenient or consistent. In
this case, it chose to do something other than what you expected.
Having expectations for undefined behavior is not reasonable.

The C standard requires the value of a freed pointer to become
indeterminate. Any attempt to evaluate an indeterminate value invokes
undefined behavior. Basically there is no way in standard C to verify
that free did what it was supposed to. Even if there were a way to
determine whether a particular piece of memory was available, how
could you tell the difference between:
1 - free failing and the memory not available for future use.
2 - free succeeding and the memory available but some other
process grabbing the memory before you could test it.


Remove del for email
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote
6 13th March 11:36
neil
External User
 
Posts: 1
Default I want my segmentation fault!


Malloc gets the memory free returns it.
Every malloc must match to a free.
Never free a pointer that was not malloc.
Never change a malloced pointer, or you lose the block.
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote
7 13th March 11:36
douglas a. gwyn
External User
 
Posts: 1
Default I want my segmentation fault!


Actually it's a standard library function, not a command.


It merely makes the previously malloced (or realloced,
or calloced) block of memory available for later
reallocation. Think of it as returning the block to
a "pool" of free memory that the malloc/realloc/calloc/
free subsystem manages. After you free a block, that
pointer value is no longer valid (until it is later
returned from another call to malloc/realloc/calloc).


Yup, that's why free is useful.

You're confusing having an address mapped into your process's
virtual address space with the addressed memory being available.
Once the previously allocated block (whose address became
mapped into your process space as a side effect of malloc's
operations) is returned via free, the storage may still lie
within your process's address space, but your program is not
allowed to access it *because it now belongs to the malloc/
realloc/calloc/free subsystem*. In particular, it may contain
link pointers and size information (referring to other free
blocks in the managed dynamic storage pool). If you mess up
that internal information, you'll break the malloc/realloc/
calloc/free subsystem, which typically causes a hard to
diagnose failure at some later point in the program.

Although actually the segmentation fault was more likely due
to ml1 having contained a null pointer value until you later
assigned it a non-null malloced value. Just because storage
is freed doesn't mean that previous pointers to it acquire
null pointer values. (You can store ******** NULL when you
deallocate them, as a safety measure.)
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote
8 13th March 11:36
neil
External User
 
Posts: 1
Default I want my segmentation fault!


A little more.
You need to structure your program better. Use of unalloced pointers is
always a bad idea.

One way to deal with this is to set all pointers equal to NULL.
You can then test for != NULL to see if it points to anything.
be sure to set it back to NULL after freeing it.
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote
9 13th March 11:37
raxitsheth2000
External User
 
Posts: 1
Default I want my segmentation fault!


Use Valgrind (Only on Linux) to findout memory leaks,

It will detect invalid free, invalid read/write (which will cause Core
dump) and UnFreed Memory and many more

http://www.valgrind.org


--raxit sheth
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote
10 13th March 18:25
geoff
External User
 
Posts: 1
Default I want my segmentation fault!


Set your compiler to higher warning levels. Your code is not runnable as listed
and will not compile properly.

Gross errors:
You forgot to include the standard headers <malloc.h> and <stdlib.h>.
You did not declare ml1, ml2 and ml3 prior to use in main().
You use copy_alloc() in your main(). This function does not exist.
(I think you intended to write copy_ml there.)

Attempting to use a pointer to freed memory is a common programmer error in C
but C as such offers little protection from it. (If any.)

Depending on your debugging environment, your OS and your C runtime libraries,
your debugger may provide a debug version of free() that will invalidate the
pointer whose memory was freed and fill the freed memory with special bytes
indicating it is dead. Then if you err and try to use that pointer in debug it
will point to an invalid address and seg fault or it will point to garbage and
your program will fail. In release mode however, there is no such protection
unless the OS does it automatically for security reasons but your C program
shouldn't rely on this.

In the sample case your first printf attempts to access an un-initialized
pointer and the runtime catches it. In the case of the second printf the pointer
ml1 is unchanged by the free() function but the contents are invalid. (Depending
on the OS and the memory load, the contents may still remain but you can never
know.)

If you are going write your own allocators, and this is what you did in
implementing alloc_ml and free_ml, then you should invalidate the pointer in the
free_ml function at runtime and not rely on your OS to do it for you. In this
case setting *ml = NULL should work nicely.

Taking some liberties with your sample like removing unused local variables from
the functions, I re-write it:

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

struct measured_list {
int length_of_list;
int * list_of_int;
};

struct measured_list * alloc_ml(int n, int * l)
{
int i;
struct measured_list *ml;
ml = (struct measured_list *) malloc(sizeof(struct measured_list));
ml->length_of_list = n;
ml->list_of_int = (int *) malloc(n*sizeof(int));
for(i=0;i<n;i++) ml->list_of_int[i] = l[i];
return ml;
}

void free_ml(struct measured_list **ml)
{
free((*ml)->list_of_int);
free(*ml);
*ml = NULL; /* invalidate the pointer */
return;
}

struct measured_list * copy_ml(struct measured_list * ml)
{
int n,*l;

struct measured_list * new_ml;
n = ml->length_of_list;
l = ml->list_of_int;
new_ml = alloc_ml(n,l);
return new_ml;
}

int main()
{
int l[3]={2,3,7};
struct measured_list *ml1, *ml2, *ml3;

/* printf("ml1->list_of_int[0] = %d\n",ml1->list_of_int[0]); */
ml1 = alloc_ml(3,l);
ml2 = copy_ml(ml1);
ml3 = copy_ml(ml2);
free_ml(&ml1);
free_ml(&ml2);
free_ml(&ml3);
printf("ml1->list_of_int[0] = %d\n", ml1->list_of_int[0]);
return 0;
}

Since free_ml sets the pointer ml to NULL the printf fails with segmentation
fault as intended. This program compiles without errors or warnings and fails as
designed in VC++ 6.0 on Windows and GCC 4.0.0 on Linux.

Now, a word about style and design: A SIGSEGV is a catastrophic failure of your
program and while it's nice to have that protection while debugging, for it to
happen in production code is to demonstrate laziness or inattention. Your
programs in debug mode should be designed to catch and report errors like this.
Learn to use the assert macro and don't forget to include <assert.h>. Your
production code should be designed to recover gracefully from errors or to
properly report them so try to catch null or bad pointers in your code before
attempting to use them.
--
comp.lang.c.moderated - moderation address: clcm@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
  Reply With Quote
Reply


Thread Tools
Display Modes




Copyright © 2006 SmartyDevil.com - Dies Mies Jeschet Boenedoesef Douvema Enitemaus -
666