LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
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 09-04-2005, 04:45 PM   #1
zaichik
Member
 
Registered: May 2004
Location: Iowa USA
Distribution: CentOS
Posts: 419

Rep: Reputation: 30
I've just created a memory leak


Hi all,

It just occurred to me that this function creates a memory leak, does it not?
Code:
char* int_to_dotted( unsigned int ipv4 ) {

        int remainder = 0;
        int octet1 = 0, octet2 = 0, octet3 = 0;
        unsigned int FIRST_OCT_MULTIPLIER = 16777216;
        unsigned int SECOND_OCT_MULTIPLIER = 65536;
        unsigned int THIRD_OCT_MULTIPLIER = 256;
        char *answer;

        answer = ( char * ) malloc( MAX_SIZE_IPADDR + 1 );
        if( answer == NULL ) {
                printf( "%s:  Out of memory in int_to_dotted().\n", myName );
                exit( -1 );
        }

        octet1 = ipv4 / FIRST_OCT_MULTIPLIER;
        ipv4 %= FIRST_OCT_MULTIPLIER;
printf( "ipv4 = %d\n", ipv4 );
        octet2 = ipv4 / SECOND_OCT_MULTIPLIER;
        ipv4 %= SECOND_OCT_MULTIPLIER;
printf( "ipv4 = %d\n", ipv4 );
        octet3 = ipv4 / THIRD_OCT_MULTIPLIER;
        ipv4 %= THIRD_OCT_MULTIPLIER;
printf( "octet1 = %d, o2 = %d, o3 = %d, o4 = %d\n", octet1, octet2, octet3, ipv4 );
        sprintf( answer, "%d.%d.%d.%d", octet1, octet2, octet3, ipv4 );
printf( "answer = %s\n", answer );
        return( answer );
}
By having it return the a variable that is dynamically allocate, I cannot free this memory. So every time it gets called, I am leaking away MAX_SIZE_IPADD + 1.

Can anyone think of a way around this, short of passing a char* to the function to store the value in?

TIA!
 
Old 09-04-2005, 04:51 PM   #2
spooon
Senior Member
 
Registered: Aug 2005
Posts: 1,755

Rep: Reputation: 51
You can always just free() the value returned by this function whenever you're done with it; since the return value ("answer") is just the pointer to the memory you allocated.

Last edited by spooon; 09-04-2005 at 04:52 PM.
 
Old 09-04-2005, 05:15 PM   #3
zaichik
Member
 
Registered: May 2004
Location: Iowa USA
Distribution: CentOS
Posts: 419

Original Poster
Rep: Reputation: 30
Hi, thanks for the reply.

OK, what I have now is this:
Code:
int callingFunction( void ) {
   char *ip;
   ip = ( char * ) malloc( MAX_SIZE_IPADDR );
   sprintf( ip, "%s", int_to_dotted( someInt );
}
So you are saying to do this:
Code:
int callingFunction( void ) {
   char *ip;
   ip = int_to_dotted( someInt );
   .
   .
   free( ip );
And that 1) work, and 2) free the memory allocated in the other function?

Thanks for your reply, again!
 
Old 09-04-2005, 10:25 PM   #4
btmiller
Senior Member
 
Registered: May 2004
Location: In the DC 'burbs
Distribution: Arch, Scientific Linux, Debian, Ubuntu
Posts: 4,290

Rep: Reputation: 378Reputation: 378Reputation: 378Reputation: 378
There are a couple of cardinal rules to malloc/free

(1) One free per malloc.
(2) Only ever pass free a pointer you got with malloc. Passing it other stuff will lead to weird results (and program crashes).

So, yes, you can malloc some memory in one function and free it in another function. But don't do something like:

Code:
char *foo;

foo = malloc(SOMESIZE);
foo = malloc(SOMETHINGELSE);
free(foo);
Dpo you see why? That code called malloc twice (on the same pointer, but freed only the second chunk. The first chunk was effectively lost, and this is bad.
 
Old 09-04-2005, 10:32 PM   #5
zaichik
Member
 
Registered: May 2004
Location: Iowa USA
Distribution: CentOS
Posts: 419

Original Poster
Rep: Reputation: 30
Hi,

Yes, I see why that is bad. But this:

Code:
char *a;
char *b;

b = malloc( someValue );
a =b;
free( a );
would work just fine. Since, after all, it's just a memory location, passing it to free by whatever name would have the same effect--assuming that memory address had been malloc'd in the first place.

Thanks for your help!
 
Old 09-04-2005, 11:54 PM   #6
sind
Member
 
Registered: Jun 2005
Posts: 75

Rep: Reputation: 15
Hi zaichik,

IMO, your best bet would be to pass int_to_dotted() a pointer to a chunk of memory, along with the size of that chunk; that way you can keep any calls to malloc() and free() in the calling function, which might help with debugging. This seems to be the convention for thread-safe functions in glibc.

If you're going to do this:

Code:
char *ip;
ip = ( char * ) malloc( MAX_SIZE_IPADDR );
sprintf( ip, "%s", int_to_dotted( someInt );
you might as well pass the malloc()'d pointer to int_to_dotted() and save an sprintf() (I'd recommend that you use snprintf(), BTW), as well saving an additional block of memory, of size (MAX_SIZE_IPADDR + 1). Just a thought.

Also, I'm interested to know why you are casting the result of malloc(), it shouldn't be necessary.

Code:
void int_to_dotted( unsigned int ipv4, char *answer, unsigned int answer_len ) {

    int remainder = 0;
    int octet1 = 0, octet2 = 0, octet3 = 0;
    unsigned int FIRST_OCT_MULTIPLIER = 16777216;
    unsigned int SECOND_OCT_MULTIPLIER = 65536;
    unsigned int THIRD_OCT_MULTIPLIER = 256;

    octet1 = ipv4 / FIRST_OCT_MULTIPLIER;
    ipv4 %= FIRST_OCT_MULTIPLIER;
    printf( "ipv4 = %d\n", ipv4 );

    octet2 = ipv4 / SECOND_OCT_MULTIPLIER;
    ipv4 %= SECOND_OCT_MULTIPLIER;
    printf( "ipv4 = %d\n", ipv4 );

    octet3 = ipv4 / THIRD_OCT_MULTIPLIER;
    ipv4 %= THIRD_OCT_MULTIPLIER;
    printf( "octet1 = %d, o2 = %d, o3 = %d, o4 = %d\n", octet1, octet2, octet3, ipv4 );

    snprintf( answer, answer_len, "%d.%d.%d.%d", octet1, octet2, octet3, ipv4 );

    printf( "answer = %s\n", answer );
}


int callingFunction( void ) {

    char *ip;
    ip = malloc( MAX_SIZE_IPADDR );
    
    /* malloc error check */

    int_to_dotted( someInt, ip, MAX_SIZE_IPADDR );

    /* Do something with ip */

    if ( ip != NULL ) {
        free( ip );
        ip = NULL;
    }

    /* Rest of fn */
}
~sind
 
Old 09-05-2005, 06:36 AM   #7
zaichik
Member
 
Registered: May 2004
Location: Iowa USA
Distribution: CentOS
Posts: 419

Original Poster
Rep: Reputation: 30
Quote:
you might as well pass the malloc()'d pointer to int_to_dotted() and save an sprintf() (I'd recommend that you use snprintf(), BTW), as well saving an additional block of memory, of size (MAX_SIZE_IPADDR + 1).
Well, that makes sense, and honestly, I don't know why I didn't just do that from the beginning.

What is the point of setting the pointer equal to NULL after it is freed? Is that to prevent accidentally trying to access the formerly pointed-to memory again?

And casting the return value of malloc()? I've always done that, as that was highly recommended in the book in which I initially learned how to use malloc, "Linux Programming by Example" by Arnold Robbins:
Quote:
Allocate the storage by calling malloc(), assigning the function's return value to the pointer variable. It is good practice to cast the return value of malloc() to that of the variable being assigned to. In C it's not required (although the compiler may generate a warning). We strongly recommend always casting the return value.
Thoughts?
 
  


Reply



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
Memory leak?! nyk Programming 10 01-24-2005 07:08 PM
Possible Memory Leak liquidcool Linux - General 3 10-07-2004 08:38 AM
possible memory leak?? matt80 Linux - General 2 07-01-2004 11:07 PM
Memory Leak when using memory debugging C program on SuSE SLES8 babalina Linux - Distributions 0 10-06-2003 09:39 AM
Memory Leak FredrikN Linux - General 4 09-17-2002 03:16 PM

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

All times are GMT -5. The time now is 05:40 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