LinuxQuestions.org
Review your favorite Linux distribution.
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 08-19-2005, 08:19 PM   #1
zaichik
Member
 
Registered: May 2004
Location: Iowa USA
Distribution: CentOS
Posts: 419

Rep: Reputation: 30
Problems in C with free( )


Hello everyone,

Hoping to get some help with a function I have written. It takes a string which is an IP address in dotted decimal notation and returns the equivalent integer value, i.e. given "1.0.0.1" it should return 16777217.

The problem I am having is memory allocation (standard n00b problem). The string gets tokenized with strtok() into its four octets, each of which is char*. I malloc memory to each octet, and strtok() the address into them. For example, when I enter the IP address "1.2.3.4", output in the debugger is as follows:
Code:
89      printf( "tempAddr = %s\n", tempAddr );
(gdb)
tempAddr = 1.2.3.4
90              octet1 = strtok( tempAddr, "." );
(gdb)
91              octet2 = strtok( NULL, "." );
(gdb)
92              octet3 = strtok( NULL, "." );
(gdb)
93              octet4 = strtok( NULL, "\0" );
(gdb)
95              free( tempAddr );
(gdb) print octet1
$1 = 0x8287020 "1"
(gdb) print octet2
$2 = 0x8287022 "2"
(gdb) print octet3
$3 = 0x8287024 "3"
(gdb) print octet4
$4 = 0x8287026 "4"
That's fine. But look what happens when I push on, and try to print out the values of the string octets with printf():
Code:
(gdb) step
97      printf( "String octets:\toctet1 = %s\toctet2 = %s\toctet3 = %s\t octet4 = %s\n", octet1, octet2, octet3, octet4 );    
(gdb)
String octets:  octet1 =        octet2 =        octet3 = 3       octet4 = 4
Oops. octet1 and octet2 suddenly have no value. What the...?
Finally, when I try to free the memory allocated to the octets, it seems that kernel says "No way!" and the program segfaults on free( octet2 ):
Code:
(gdb) step
105             free( octet1 );
(gdb)
106             free( octet2 );
(gdb)

Program received signal SIGSEGV, Segmentation fault.
0x00e78057 in _int_free () from /lib/tls/libc.so.6
I'm lost. I have copied and pasted this code from another function I have that needs to parse an IP address into octets, and it works fine in that function.

Looking at the above output, the addresses look right. The allocation is
Code:
octetX = ( char * ) malloc( 4 );
and it looks like they have each gotten 4 bytes.

I have posted the code at http://zaichik.org/convert_ip.c along with a few sample runs in a comment block at the bottom. Let me know if that is not kosher and I will post it here.

TIA for any ideas.
 
Old 08-20-2005, 12:41 AM   #2
sind
Member
 
Registered: Jun 2005
Posts: 75

Rep: Reputation: 15
Hi zaichik,

IIRC strtok() returns a pointer to the substring that it finds, which means that free()ing the memory for the original string (tempAddr) will make those pointers invalid - there is no guarantee that the data will remain there, and it is possible that accessing that area of memory will raise a segmentation fault.

When you call strtok() and put the return value in one of your octet pointers, you are overwriting the address stored in those pointers, not storing the octet characters in the memory that you have allocated. This creates two problems; first, it makes a memory hole, as you've allocated memory and no longer have the address to it, thus the memory cannot be freed until the process is finished. Secondly, a call to free() on one of your octet pointers will be invalid, because they are pointing to an area of memory that has not been allocated by a call to malloc() (you might get away with it for octet1 because it will likely point to the address allocated by malloc() for tempAddr - Edit: although seeing as you have already free()d that memory this can cause even more trouble).

I hope that that makes some kind of sense... I'm a bit tired today. I didn't look at your code thouroughly so there might be some other problems...

HTH

~sind

Edit:
BTW, as you can read elsewhere in this forum, it is not necessarily a good idea to cast the return value of malloc(). See http://www.linuxquestions.org/questi...99#post1727999

Also, it might be worthwhile using sscanf() rather than strtok(), like so:

Code:
char *ip = "12.34.56.789";
int oct1, oct2, oct3, oct4;

sscanf(ip, "%d.%d.%d.%d", &oct1, &oct2, &oct3, &oct4);

printf("oct1: %d, oct2: %d, oct3: %d, oct4: %d\n", oct1, oct2, oct3, oct4);

Last edited by sind; 08-20-2005 at 03:33 AM.
 
Old 08-20-2005, 05:55 PM   #3
zaichik
Member
 
Registered: May 2004
Location: Iowa USA
Distribution: CentOS
Posts: 419

Original Poster
Rep: Reputation: 30
Hello sind,

OMG...

I feel stupid now. I was even using sscanf in the original code. I used strtok to break the IP into string octets, and then
sscanf to read the string octets into int octets. Original code has gone from:
Code:
int dotted_to_int( char *addr ) {

        char *tempAddr;
        int answer;
        char *octet1;
        char *octet2;
        char *octet3;
        char *octet4;
        int oct1 = 0, oct2 = 0, oct3 = 0, oct4 = 0;
        int FIRST_OCT_MULTIPLIER = 16777216;
        int SECOND_OCT_MULTIPLIER = 65536;
        int THIRD_OCT_MULTIPLIER = 256;
        char *myName = "convert_ip";

        tempAddr = ( char * ) malloc( MAX_SIZE_IPADDR );
        if( tempAddr == NULL ) {
	fprintf( stderr, "%s: Out of memory in dotted_to_int()\n", myName );
	exit( -1 );
        }

         octet1 = ( char * ) malloc( MAX_SIZE_OCTET );
         if( octet1 == NULL ) {
                fprintf( stderr, "%s: Out of memory in dotted_to_int()\n", myName );
	free( tempAddr );
                exit( -1 );
        }

        octet2 = ( char * ) malloc( MAX_SIZE_OCTET );
        if( octet2 == NULL ) {
                fprintf( stderr, "%s: Out of memory in dotted_to_int()\n", myName );
                free( tempAddr );
	free( octet1 );
                exit( -1 );
        }
	
        octet3 = ( char * ) malloc( MAX_SIZE_OCTET );
        if( octet3 == NULL ) {
                fprintf( stderr, "%s: Out of memory in dotted_to_int()\n", myName );
                free( tempAddr );
                free( octet1 );
	free( octet2 );
                exit( -1 );
        }

        octet4 = ( char * ) malloc( MAX_SIZE_OCTET );
        if( octet4 == NULL ) {
                fprintf( stderr, "%s: Out of memory in dotted_to_int()\n", myName );
                free( tempAddr );
                free( octet1 );
	free( octet2 );
	free( octet3 );
                exit( -1 );
        }

        strcpy( tempAddr, addr );
        octet1 = strtok( tempAddr, "." );
        octet2 = strtok( NULL, "." );
        octet3 = strtok( NULL, "." );
        octet4 = strtok( NULL, "\0" );

        free( tempAddr );
                  
        sscanf( octet1, "%d", &oct1 );
        sscanf( octet2, "%d", &oct2 );
        sscanf( octet3, "%d", &oct3 );
        sscanf( octet4, "%d", &oct4 );

        answer = oct1 * FIRST_OCT_MULTIPLIER + oct2 * SECOND_OCT_MULTIPLIER + oct3 * THIRD_OCT_MULTIPLIER + oct4;
        free( octet1 );
        free( octet2 );
        free( octet3 );
        free( octet4 );
        return( answer );
}
to

Code:
int dotted_to_int( char *addr ) {

        int answer;
        int oct1 = 0, oct2 = 0, oct3 = 0, oct4 = 0;
        int FIRST_OCT_MULTIPLIER = 16777216;
        int SECOND_OCT_MULTIPLIER = 65536;
        int THIRD_OCT_MULTIPLIER = 256;

        sscanf( addr, "%d.%d.%d.%d", &oct1, &oct2, &oct3, &oct4 );
        answer = oct1 * FIRST_OCT_MULTIPLIER + oct2 * SECOND_OCT_MULTIPLIER + oct3 * THIRD_OCT_MULTIPLIER + oct4;
        return( answer );
}
Embarrassing, really.

Thanks again, sind. Good stuff!
 
Old 08-20-2005, 08:56 PM   #4
jonaskoelker
Senior Member
 
Registered: Jul 2004
Location: Denmark
Distribution: Ubuntu, Debian
Posts: 1,524

Rep: Reputation: 47
That's why you *don't* measure programmer productivity in #lines of code

--Jonas
 
Old 08-21-2005, 06:25 AM   #5
sind
Member
 
Registered: Jun 2005
Posts: 75

Rep: Reputation: 15
Quote:
zaichik wrote:
Thanks again, sind. Good stuff!
Glad that I could help.

~sind
 
  


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
help: ALSA OSS/Free Emulation problems Onyx^ Linux - Software 0 08-05-2004 07:15 AM
Free Space Problems chalewa4bambu Linux - Software 2 03-23-2004 12:52 PM
Problems with tar wasting free HD space ferrantepunto Linux - Software 6 08-09-2003 11:37 PM
Free, free,FREE=? no money, = Freedom? murshed Linux - Newbie 8 01-20-2003 07:01 AM
X Free 86 Display problems... justiceisblind Linux - Newbie 19 02-17-2002 09:19 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:51 AM.

Main Menu
Advertisement
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
Open Source Consulting | Domain Registration