GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 11-Jul-2004, 23:51
spike666's Avatar
spike666 spike666 is offline
New Member
 
Join Date: Mar 2004
Posts: 17
spike666 is on a distinguished road

segfault on malloc (C)


I've got an issue right now with a very special-case segfault in my code. It only happens on my x86 linux box (as opposed to my PPC one).

my problem is that one of my functions segfaults on this line:

Code:
char *rawEntry = (char*)malloc(GCM_FST_ENTRY_LENGTH);

where GCM_FST_ENTRY_LENGTH is 12.

how I know what line:
Code:
Program received signal SIGSEGV, Segmentation fault. 0x4007acfb in mallopt () from /lib/libc.so.6 (gdb) where #0 0x4007acfb in mallopt () from /lib/libc.so.6 #1 0x40079e33 in malloc () from /lib/libc.so.6 #2 0x0804b523 in GCMGetNthFileEntry (ifile=0x804f050, n=7) at GCMextras.c:135 #3 0x0804b67c in GCMGetFileEntryAtPath (ifile=0x804f050, path=0x804d3c0 "/opening.bnr") at GCMextras.c:186 #4 0x0804c955 in main (argc=2, argv=0xbffff894) at fileentrytest.c:24

line 135 in GCMextras.c is the above line...

it doesn't segfault every time the function is called, but only in a specific case. Any idea about what could be causing it? I've never had something segfault on an malloc before, so I don't even know where to start looking for info (I JUST started learning to use gdb early last week).
  #2  
Old 12-Jul-2004, 07:28
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Quote:
Originally Posted by spike666
I've got an issue right now with a very special-case segfault in my code. It only happens on my x86 linux box (as opposed to my PPC one).

my problem is that one of my functions segfaults on this line:

Code:
char *rawEntry = (char*)malloc(GCM_FST_ENTRY_LENGTH);

where GCM_FST_ENTRY_LENGTH is 12.

how I know what line:
Code:
Program received signal SIGSEGV, Segmentation fault. 0x4007acfb in mallopt () from /lib/libc.so.6 (gdb) where #0 0x4007acfb in mallopt () from /lib/libc.so.6 #1 0x40079e33 in malloc () from /lib/libc.so.6 #2 0x0804b523 in GCMGetNthFileEntry (ifile=0x804f050, n=7) at GCMextras.c:135 #3 0x0804b67c in GCMGetFileEntryAtPath (ifile=0x804f050, path=0x804d3c0 "/opening.bnr") at GCMextras.c:186 #4 0x0804c955 in main (argc=2, argv=0xbffff894) at fileentrytest.c:24

line 135 in GCMextras.c is the above line...

it doesn't segfault every time the function is called, but only in a specific case. Any idea about what could be causing it? I've never had something segfault on an malloc before, so I don't even know where to start looking for info (I JUST started learning to use gdb early last week).


The problem with segfaults is that even though they occur at one place, they could be a result of something else that you have done in another place. They can be *hell* to track down. What I try to do is trace what I am doing before the failing call. Have I overwritten in another location? Have I free'd a non-valid location?

You may want to play with the setting of MALLOC_CHECK_. From the linux man page:
Code:
Recent versions of Linux libc (later than 5.4.23) and GNU libc (2.x) include a malloc implementation which is tun- able via environment variables. When MALLOC_CHECK_ is set, a special (less efficient) implementation is used which is designed to be tolerant against simple errors, such as double calls of free() with the same argument, or overruns of a single byte (off-by-one bugs). Not all such errors can be protected against, however, and memory leaks can result. If MALLOC_CHECK_ is set to 0, any detected heap corruption is silently ignored; if set to 1, a diag- nostic is printed on stderr; if set to 2, abort() is called immediately. This can be useful because otherwise a crash may happen much later, and the true cause for the problem is then very hard to track down.

By setting this to 1 or 2, you may be able to find where your memory trashing is actually starting.

Hope this helps,
d
  #3  
Old 12-Jul-2004, 09:07
spike666's Avatar
spike666 spike666 is offline
New Member
 
Join Date: Mar 2004
Posts: 17
spike666 is on a distinguished road
well, believe it or not... setting MALLOC_CHECK_=1 (or 2) actually eliminates the bug... So now I'm even more confused...

Also, something I failed to mention earlier, I just realized... when I get the segfault (when MALLOC_CHECK_=0):

Code:
... alloc'd enry 1 alloc'd enry 0 free(): invalid pointer 0x804f1e0! alloc'd entry 2 alloc'd entry 0 free(): invalid pointer 0x804f220! alloc'd entry 3 alloc'd entry 0 free(): invalid pointer 0x804f260! alloc'd enry 4 alloc'd entry 0 free(): invalid pointer 0x804f2a0! alloc'd entry 5 alloc'd entry 0 alloc'd entry 6 free(): invalid pointer 0x804f2d0! alloc'd entry 0 Segmentation fault

when it segfaults, that's the way it goes... I stuck some debugging output after each malloc (alloc'd entry X), which normally could be safely ignored, but it switches where the error happens right before segfaulting...

any other suggestions of what I can do to track it down?

thanks


...spike

Quote:
Originally Posted by dsmith
The problem with segfaults is that even though they occur at one place, they could be a result of something else that you have done in another place. They can be *hell* to track down. What I try to do is trace what I am doing before the failing call. Have I overwritten in another location? Have I free'd a non-valid location?

You may want to play with the setting of MALLOC_CHECK_. From the linux man page:
Code:
Recent versions of Linux libc (later than 5.4.23) and GNU libc (2.x) include a malloc implementation which is tun- able via environment variables. When MALLOC_CHECK_ is set, a special (less efficient) implementation is used which is designed to be tolerant against simple errors, such as double calls of free() with the same argument, or overruns of a single byte (off-by-one bugs). Not all such errors can be protected against, however, and memory leaks can result. If MALLOC_CHECK_ is set to 0, any detected heap corruption is silently ignored; if set to 1, a diag- nostic is printed on stderr; if set to 2, abort() is called immediately. This can be useful because otherwise a crash may happen much later, and the true cause for the problem is then very hard to track down.

By setting this to 1 or 2, you may be able to find where your memory trashing is actually starting.

Hope this helps,
d
  #4  
Old 13-Jul-2004, 07:20
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Quote:
Originally Posted by spike666

Code:
... alloc'd enry 1 alloc'd enry 0 free(): invalid pointer 0x804f1e0! alloc'd entry 2 alloc'd entry 0 free(): invalid pointer 0x804f220! alloc'd entry 3 alloc'd entry 0 free(): invalid pointer 0x804f260! alloc'd enry 4 alloc'd entry 0 free(): invalid pointer 0x804f2a0! alloc'd entry 5 alloc'd entry 0 alloc'd entry 6 free(): invalid pointer 0x804f2d0! alloc'd entry 0 Segmentation fault
...spike

Hi Spike.

That happens to me sometimes to where a MALLOC_CHECK will actually fix a problem due to it making malloc a tad more fault tolerant. IMO, this is not a solution that you want to stick with, because something somewhere is getting trashed.

What is strange is all of your free calls shown above. They all claim to be trying to free an invalid pointer. Why is that? Can you post a small code snippet that can be telling enough as to what is happening here?
  #5  
Old 13-Jul-2004, 08:37
spike666's Avatar
spike666 spike666 is offline
New Member
 
Join Date: Mar 2004
Posts: 17
spike666 is on a distinguished road
Quote:
Originally Posted by dsmith
Hi Spike.

That happens to me sometimes to where a MALLOC_CHECK will actually fix a problem due to it making malloc a tad more fault tolerant. IMO, this is not a solution that you want to stick with, because something somewhere is getting trashed.

What is strange is all of your free calls shown above. They all claim to be trying to free an invalid pointer. Why is that? Can you post a small code snippet that can be telling enough as to what is happening here?

yeah, I'm not saying that I'm accepting that as being a solution... I found a small memory leak in my code that changed how soon I get the error (after patching that leak, it made this error happen almost immediately rather than after a couple iterations...).

I'll post a little code that I think has to do with this error. This is an opensource project hosted on sourceforge, so you can take a look in the CVS if you'd like, if you need to see more.

http://gcmtool.sf.net

This is the code that I fixed the leak in... I don't think this is the problem:

CPP / C++ / C Code:
char *nthPathComponent(char *source, int n, char *buf) {
        /*
        **      returns a pointer to buf
        **      sets buf to the nth path component of source.
        **      nthPathComponent("this/path/is/cool", 2) returns "is"
        */

        if (!source || !buf) return NULL;

        int i = 0;
        char *pathItem = (char*)malloc(strlen(source));
        char *os1 = pathItem;
        char *s = source;

        for (i = 0; (i < n) && (s = index(s, kPathSeparator)); i++, *s++);

        if (!s) {
                printf("not enough path components!!!!!\n");
                free(pathItem);
                return NULL;
        }

        while (*s != kPathSeparator && (*os1++ = *s++));

        *os1++ = 0;

        strcpy(buf, pathItem);

        free(pathItem);

        return buf;
}

Here is the function that I'm segfaulting in:

CPP / C++ / C Code:
GCMFileEntryStruct *GCMGetNthFileEntry(FILE *ifile, int n) {
        char *rawEntry = (char*)malloc(GCM_FST_ENTRY_LENGTH);
        printf("alloc'd entry %d\n", n); //debugging...
        GCMGetNthRawFileEntry(ifile, n, rawEntry);
        GCMFileEntryStruct *entry = GCMRawFileEntryToStruct(rawEntry, n);
        free(rawEntry);

        return entry;
}

it segfaults on the malloc() line above...

and here's one last snippet... this function calls the above function (GCMGetNthFileEntry()):

CPP / C++ / C Code:
GCMFileEntryStruct *GCMGetFileEntryAtPath(FILE *ifile, char *path) {
        /*
        **  returns the file entry at path
        **  entry WILL have it's filename attribute set.
        **
        **  path must be an absolute path (ie: /this/is/the/file.raw)
        **  it must have a leading /
        */

        int curPathComponent = 1;
        int i = 0;
        int entryCount = GCMGetFileEntryCount(ifile);

        // loop through all of the file entries...
        for (i = 1; i < entryCount; i++) {
                // grab the current entry...
                GCMFileEntryStruct *e = GCMGetNthFileEntry(ifile, i);
                GCMFetchFilenameForFileEntry(ifile, e);

                if (!e) {
                        printf("an error occurred! e is NULL!\n");
                        exit(1);
                }

                // if this entry matches the next pathComponent, then....
                char *nthPC = (char*)malloc(512);
                if (strcmp(e->filename, nthPathComponent(path, curPathComponent, nthPC)) == 0) {

                        if (curPathComponent == pathComponentCount(path)) {
                                // it's the file we're looking for! return it!
                                return e;
                        } else {
                                // otherwise... let's 'cd' into that directory, and continue...
                                curPathComponent++;
                        }

                } else if (e->isDir) {
                        // it's not what we're looking for, and it's a directory, 
                        // so just skip over everything and move onto the next file...

                        i = (int)e->length - 1;
                }
                free(nthPC);

                // free our working entry so we can move on to the next one...
                GCMFreeFileEntryStruct(e);
                //free(e);
        }

        //file not found, so just return NULL...
        return NULL;
}

As you can see, I'm calling a lot of my own functions here... I don't want to post them all, but like I said, check out the CVS from my project page if you want to see anything outside of what's posted here... you can browse it from a web browser, even. =)

I've been stepping through my code trying to find any place where I write outside of the bounds of my char*, but I can't seem to find anything. Is there any way of setting a breakpoint in gdb for when something is free()'d? I'd like to know what invalid pointer I'm freeing...

Also, I've compared the results of my calculations between x86 and PPC (I'm reading from a file that stores multibyte int values in big-endian, and since this error only happens on little endian (x86), I thought that might be the issue), but everything is exactly the same. I even had it run through a file with 5000 entries and compare them, and they're identical (md5sum of the output). So I'm pretty sure it's not a misplaced ntohl().

Thanks.
Last edited by LuciWiz : 25-Mar-2006 at 10:47. Reason: Please insert your C code between [c] & [/c] tags
  #6  
Old 13-Jul-2004, 09:07
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
This may be a very dumb comment, but do you have enough room to put in your Null terminator when you only allocate enough for the strlen(source). I always do a +1 to make sure that there is room for the Null character.

CPP / C++ / C Code:
char *nthPathComponent(char *source, int n, char *buf) {
        /*
        **      returns a pointer to buf
        **      sets buf to the nth path component of source.
        **      nthPathComponent("this/path/is/cool", 2) returns "is"
        */

        if (!source || !buf) return NULL;

        int i = 0;
        char *pathItem = (char*)malloc(strlen(source)); 
//I would use: char *pathItem = (char*) malloc(strlen(source)+1));
        char *os1 = pathItem;
        char *s = source;

        for (i = 0; (i < n) && (s = index(s, kPathSeparator)); i++, *s++);

        if (!s) {
                printf("not enough path components!!!!!\n");
                free(pathItem);
                return NULL;
        }

//Right here you are potentially copying the full value of source into pathitem.  
        while (*s != kPathSeparator && (*os1++ = *s++));

//Now unless the above loop exitted because of a kPathSeperator, you are adding null at the first position over your allocated memory.
        *os1++ = 0;

        strcpy(buf, pathItem);

        free(pathItem);

        return buf;
}

That may just be my paranoia, but it seems like you are possibly placing a character outside of your allocated space.

PS - by using c tags instead of code tags, you can get nice syntax highlighting when you post your c/c++ code. See the first sticky thread in this sub-forum for more details.
  #7  
Old 13-Jul-2004, 11:40
spike666's Avatar
spike666 spike666 is offline
New Member
 
Join Date: Mar 2004
Posts: 17
spike666 is on a distinguished road
Quote:
Originally Posted by dsmith
This may be a very dumb comment, but do you have enough room to put in your Null terminator when you only allocate enough for the strlen(source). I always do a +1 to make sure that there is room for the Null character.

CPP / C++ / C Code:
char *nthPathComponent(char *source, int n, char *buf) {
        /*
        **      returns a pointer to buf
        **      sets buf to the nth path component of source.
        **      nthPathComponent("this/path/is/cool", 2) returns "is"
        */

        if (!source || !buf) return NULL;

        int i = 0;
        char *pathItem = (char*)malloc(strlen(source)); 
//I would use: char *pathItem = (char*) malloc(strlen(source)+1));
        char *os1 = pathItem;
        char *s = source;

        for (i = 0; (i < n) && (s = index(s, kPathSeparator)); i++, *s++);

        if (!s) {
                printf("not enough path components!!!!!\n");
                free(pathItem);
                return NULL;
        }

//Right here you are potentially copying the full value of source into pathitem.  
        while (*s != kPathSeparator && (*os1++ = *s++));

//Now unless the above loop exitted because of a kPathSeperator, you are adding null at the first position over your allocated memory.
        *os1++ = 0;

        strcpy(buf, pathItem);

        free(pathItem);

        return buf;
}

That may just be my paranoia, but it seems like you are possibly placing a character outside of your allocated space.

PS - by using c tags instead of code tags, you can get nice syntax highlighting when you post your c/c++ code. See the first sticky thread in this sub-forum for more details.

thanks for the tip about the c tag!!!! oh man... that's sweet... unfortunately I don't need to post any more code... or, fortunately, rather.

That strlen()+1 fixed my app. I didn't think that would have any bearing on what was going wrong and it still doesn't really explain why only passing "/opening.bnr" to my GCMGetFileEntryAtPath() function was the only thing that would segfault it, but since that's fixed, now, I'm happy. hopefully, there isn't some other mysterious string that will crash my app, now. The next step is to do a stress test and fetch thousands of files by their absolute paths to see how it handles.

Now I just have to make sure I didn't screw up in any more cases. I forgot that strlen doesn't include the \0...

Thanks dude... I've got another issue which I'm going to post in another thread tonight if I can't get it resolved.
  #8  
Old 15-Jul-2004, 14:11
Pandiani Pandiani is offline
New Member
 
Join Date: May 2004
Location: The Balkans
Posts: 16
Pandiani is on a distinguished road
Excuse me, this question is not about code.
My native language is not English, so I dont know what segfault mens. Is there any synonym. I didn't find that word in my dictionary.
Thanks
  #9  
Old 15-Jul-2004, 14:45
dsmith's Avatar
dsmith dsmith is offline
Senior Member
 
Join Date: Jan 2004
Location: Utah, USA
Posts: 1,351
dsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of lightdsmith is a glorious beacon of light
Quote:
Originally Posted by Pandiani
Excuse me, this question is not about code.
My native language is not English, so I dont know what segfault mens. Is there any synonym. I didn't find that word in my dictionary.
Thanks

segfault = Segmentation Fault

If you work under *nix it is the most common error to get from a badly behaving program.
 
 

Recent GIDBlogProblems with the Navy (Officers) by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
malloc function Rosmayati C Programming Language 5 18-May-2004 20:08
new to C, need an explanation andre C Programming Language 18 23-Mar-2004 10:09

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 14:04.


vBulletin, Copyright © 2000 - 2010, Jelsoft Enterprises Ltd.