LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 03-16-2005, 12:06 PM   #1
Miaire
LQ Newbie
 
Registered: Jan 2005
Location: Atlanta, GA
Distribution: Fedora Core 3
Posts: 11

Rep: Reputation: 0
in C, segmentation fault on free, and about double free


Segmentation Fault on free

My partner and I are having some difficulty with a client-server application that we are trying to do.

On the client side, there seems to be a problem with freeing a char * where if the code is there, we get a segmentation fault while if it isn't there, there's no error. It's kind of weird because there's a similar char * along side it with mostly the similar function, but the other one doesn't have such problems when freeing it.

Here are some relevant codes regarding it. char *firstcard is the one that is problematic, char *token is the one without problems.
Code:
char *token, *firstcard;
// some more code here
token = (char *)malloc(20);
firstcard = (char *)malloc(4);

while(strcmp(buf,"quit") != 0 ) {

// some more code here
    token = strtok(cp, delim);
    firstcard = strtok(NULL,delim);

// some more code here
}

// some more code here
free(token);
free(firstcard); // makes segmentation fault, no clue why
}
Basically that's how they were used, inside a loop or sometimes outside of it. I don't think it makes any sense so I'm putting the entire function where all these are in below at the bottom of this post.

I've isolated the problem to be free(firstcard) because I had some mvwprint, update_panels, and doupdate just above it and when I switch it around to either be on top or below, I would get the error first, or last after the printing.

The function with a segmentation fault problem
Code:
void *recvfunc(){
    int numbytes;
    const char delim[] = " .,;:!-";
    char *cp;
    char *token, *firstcard;
    char temp[65];
    int i, j, usernumber, numofcards, handtotal;
    
    token = (char *)malloc(20);
    firstcard = (char *)malloc(4);
    
    while(strcmp(buf,"quit") != 0 ) {
        strcpy( temp, "" );
        numbytes = 0;
        if ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1) {
            perror("recv");
            close(sockfd);
            exit(1);
        }
        //tokenize buf
        //mvwprintw(window,2,1,"Received: %s", buf);
        cp = (char *)strdup (buf);
        token = strtok(cp, delim);
        if(strcmp(token,"start") == 0) {
            player = atoi(strtok(NULL, delim))+1;
            MAXUSERS = atoi(strtok(NULL, delim));
            mvwprintw(window, 1, 1, "You are player %d", player);
            for(i=0; i<MAXUSERS; i++)
                mvwprintw(window, 2+(i*3), 1, "Player %d", i+1);          
        }
        else if(strcmp(token,"hand") == 0) {
            while( token = strtok(NULL, delim) ){
                if ( strcmp( token, "\n" ) != 0 ){
                    sprintf( temp, "%s%s%s ", temp, token, strtok(NULL, delim) );
                }
            }
            clearline(window, player*3);
            mvwprintw(window, player*3, 5, "Hand: %s", temp );
        }
        else if(strcmp(token,"otherhand") == 0) {
            while( (token = strtok(NULL, delim)) && (strcmp( token, "\n") != 0)){
                usernumber = atoi(token);        
                firstcard = strtok(NULL,delim);
                numofcards = atoi(strtok(NULL, delim));
                sprintf(temp, "First card: %s, Number of cards: %d  ", firstcard, numofcards);
            
                if( (player - 1) != usernumber ){
                    clearline(window, ((usernumber+1)*3));
                    mvwprintw(window, ((usernumber+1)*3), 5,"%s", temp);
                }
            }
        }
        else if( strcmp(token,"handtotal") == 0 ){
            mvwprintw(window, player*3-1, 10, "Hand total:       " );
            handtotal = atoi(strtok(NULL, delim));
            if (handtotal < 22){
                mvwprintw(window, player*3-1, 22, "%d", handtotal);
            }
            else{
                mvwprintw(window, player*3-1, 22, "*BUST*");
            }
        }
        else if( strcmp(token,"action") == 0 ){
            usernumber = atoi(strtok(NULL,delim));
            mvwprintw(window,(usernumber+1)*3+1, 5, "Last action:       ");
            mvwprintw(window,(usernumber+1)*3+1, 18, "%s", strtok(NULL,delim));
        }
        else if( strcmp(token,"winner") == 0 ){
            clearline(window, LINES - 5);
            mvwprintw(window, LINES - 5,4,"Last round %s", buf );
        }
        else if( strcmp(token, "values") == 0 ){
            mvwprintw(window, LINES - 6,4,"Last round %s", buf );
            // clear the last action part
            for( i = 0; i < MAXUSERS; i++ ){
                clearline( window, ((i+1)*3 )+1 );
            }
            update_panels();
            doupdate();
        }

        update_panels();
        doupdate();
        free(cp);
    }
    clearline(window, LINES -3 );
    clearline(window, LINES -2 );
    mvwprintw( window, LINES -2, 2, "Press any key to quit" );
    free(token);
    update_panels();
    doupdate();
//    free(firstcard); // makes segmentation fault, no clue why
}
If I remove the comment out of free, I get a segmentation fault, none if otherwise.


Double Free reporting in Fedora, not in Slackware

Also, when we try to compile and run the program in slackware 10.0 (gcc 3.3.4), there aren't any errors when we try to compile and run the program but in Fedora, we get something like a glibc error about double free which is just as hard to spot so we just removed free, here and there to try and fix it. It's on the server part of the problem. And we've isolated it to this part:
Code:
char *getfirstcard( char *firstcard, char *hand ){
    char *temphand, *tempchar;
    tempchar = (char *)malloc(3);
    temphand = (char *)malloc( sizeof(hand) );
    
    strcpy( temphand, hand );
    tempchar = strtok( temphand, " ");
    sprintf( firstcard, "%s%s", tempchar, strtok( NULL, " " ) );

    free( tempchar );
    free( temphand );

    return firstcard;
}
These are the other codes related to it that might give some clue but I don't really know.
Code:
// called together with getfirstcard
int numofcards( char *hand ){
    char *temphand;
    int numofcards = 0;
    temphand = (char *)malloc(sizeof(hand) );
    strcpy( temphand,hand );
    strtok( temphand, " " );
    while( strtok( NULL, " " ) ){
        numofcards++;
        strtok( NULL, " " );
    }

    free( temphand );
    return numofcards;
}

// calls the above 2 functions together
void getotherhand(){
    char temp[5];
    int i;
    strcpy( otherhand, "" );
    for( i = 0; i < MAXUSERS; i++ ) {
        sprintf( otherhand, "%s %d %s %d", otherhand, i, 
            getfirstcard(temp, hand[i]), numofcards(hand[i] ) );
    }
}
I was wondering why removing the free of getfirstcard solves the problem of double free, and how come Slackware doesn't report anything wrong.
 
Old 03-16-2005, 12:32 PM   #2
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: ubuntu
Posts: 2,530

Rep: Reputation: 108Reputation: 108
I did read all of it carefully, but here the reason for at least one of your problems:
Quote:
Code:
char *getfirstcard( char *firstcard, char *hand ){
    char *temphand, *tempchar;
    tempchar = (char *)malloc(3);
    temphand = (char *)malloc( sizeof(hand) );
    
    strcpy( temphand, hand );
    tempchar = strtok( temphand, " ");
    sprintf( firstcard, "%s%s", tempchar, strtok( NULL, " " ) );

    free( tempchar );
    free( temphand );

    return firstcard;
}
strtok() returns a pointer to the same buffer it is searching for a space (" ").

Code:
    tempchar = (char *)malloc(3);
    temphand = (char *)malloc( sizeof(hand) );
    /* ... */
    tempchar = strtok( temphand, " ")
So after: tempchar = strtok( temphand, " ")
tempchar is assigned a new addres inside the buffer malloc()'ed to temphand. The original address of tempchar is now lost, so the buffer (maloc(3)) can not be freed anymore, because you don't have pointer to in anymore.

tempchar is pointing somewhere into the same buffer as temphand, so you are trying to free the same buffer twice!

This is one of the reasons I guess why the man page says:
Quote:
"Never use these functions. If you do, note that:
[...]
 
Old 03-16-2005, 12:35 PM   #3
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: ubuntu
Posts: 2,530

Rep: Reputation: 108Reputation: 108
Instead, do something like this:
Code:
char *getfirstcard( char *firstcard, char *hand ){
    char *temphand, *tempchar, char *tmp;
    tempchar = (char *)malloc(3);
    temphand = (char *)malloc( sizeof(hand) );
    
    strcpy( temphand, hand );
    tmp = strtok( temphand, " ");
    sprintf( firstcard, "%s%s", tmp, strtok( NULL, " " ) );

    free( tempchar );
    free( temphand );

    return firstcard;
}
By the way: what is strtok( NULL, " " ) supposed to do?
 
Old 03-16-2005, 12:52 PM   #4
Miaire
LQ Newbie
 
Registered: Jan 2005
Location: Atlanta, GA
Distribution: Fedora Core 3
Posts: 11

Original Poster
Rep: Reputation: 0
Thanks for replying I haven't read the above well yet but I'll just post this because you probably would have something to add.

strtok( NULL, " " ) gives the next token for the previous strtok with a char argument. Like say, arg is "hello abc xyz". strtok(arg, " ") returns hello. If it is followed by strtok( NULL, " " ), it returns abc, then if ran again, returns xyz, then finally returns null I think.

edit: oh, the double free makes perfect sense, thanks! But I was just wondering, how come Fedora tells me the error while Slackware doesn't?

edit2: And now I'm guessing that the segmentation fault problem is another effect for the double free problem. I'm taking a break, I'll try everything later and post what happens.

Last edited by Miaire; 03-16-2005 at 12:57 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
*** glibc detected *** malloc() / free()/ double RohanShrivastav Programming 12 10-01-2012 11:08 AM
FC3 glibc detected *** double free or corruption: josedragone Fedora 5 09-17-2009 11:16 PM
*** glibc detected *** double free or corruption (!prev): 0x082c1120 *** eXor Slackware 6 04-11-2008 09:47 AM
Segmentation fault for free() leiyang Programming 14 08-25-2004 05:52 PM
Free, free,FREE=? no money, = Freedom? murshed Linux - Newbie 8 01-20-2003 08:01 AM


All times are GMT -5. The time now is 04:16 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration