Thread: Returning pointer to allocated memory on the heap

  1. #1
    Registered User
    Join Date
    Dec 2009
    Posts
    5

    Returning pointer to allocated memory on the heap

    I am experimenting with C and trying to write a linked list. The LLCreateNode function is meant to return a pointer to a node allocated with malloc. However, after executing the call to LLCreateNode in main, tmp is still pointing to garbage that has nothing to do with the address returned by malloc and thus an error is milliseconds away.

    I initially thought it may be because I cannot return a pointer from a function yet I found several examples with a similar implementation, one in C Programming by K&R. What is wrong? I am using NetBeans 6.8 with the GCC compiler included in Mac OS X.

    Code:
    int main(int argc, char** argv) {
    
        struct Node* tmp = NULL;
        struct LinkedList *list = NULL;
    
    
        printf( "Declared the list" );
        LLInitialize( &list );
        printf("Initialized the list");
    
        tmp = LLCreateNode( 10 );
        LLAppendNode( &list, tmp );
        printf( "Appended node" );
        LLPrintList( list );
    }
    
    /*****Linked List Implementation*****/
    #include "LinkedList.h";
    
    int LLInitialize(struct LinkedList **list);
    struct Node* LLCreateNode( int data );
    
    
    int LLInitialize(struct LinkedList **list) {
    
        (*list) = (struct LinkedList*)malloc(sizeof(struct LinkedList));
        (*list)->head = NULL;
        (*list)->tail = NULL;
    
        if(*list == NULL)
            return RT_FAIL;
    
        return RT_SUCCESS;
    }
    
    struct Node* LLCreateNode(int data) {
        
        struct Node *node = malloc(sizeof(struct Node));
        node->data = data;
        node->next = NULL;
    
        return node;
    }
    
    int LLAppendNode(struct LinkedList **list, struct Node* node) {
    
        if( (*list)->head == NULL ) {
            (*list)->head = node;
            (*list)->tail = node;
        }
        else
        {
            (*list)->tail->next = node;
            (*list)->tail = node;
    
        }
    
    }

  2. #2
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    How do you know it is pointing to garbage? It can't “still” be pointing to garbage because it was initially NULL. It is clearly being set with a value returned by LLCreateNote(). How are you verifying that this value is not correct?

    It's possible you've forgotten a header or two; make sure you're building with -Wall and addressing all warnings you see. On systems where ints and pointers are different sizes, this can be a real issue.

    Incidentally, in LLInitialize(), you want to check whether malloc() returned NULL before you make use of *list.

  3. #3
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    For starters, you don't add a ; to the end of #define. Also, your function prototypes (which is what I assume is in the .h you're including) should be available before you start using them. The include should be at the top.

    Why do you have an initialize function? Why aren't you just reusing your create node function?


    Quzah.
    Hope is the first step on the road to disappointment.

  4. #4
    Registered User
    Join Date
    Dec 2009
    Posts
    5
    Quote Originally Posted by cas View Post
    How do you know it is pointing to garbage? It can't “still” be pointing to garbage because it was initially NULL. It is clearly being set with a value returned by LLCreateNote(). How are you verifying that this value is not correct?
    In the debugger I am comparing the return address given by malloc with the return address given to tmp.

    Inside LLCreateNode() address returned by malloc is (struct Node *) 0x100100090.

    Outside LLCreateNode() the value received by tmp is: 0x100090.

    Clearly some bits are lost and I do not understand why.

    It's possible you've forgotten a header or two; make sure you're building with -Wall and addressing all warnings you see. On systems where ints and pointers are different sizes, this can be a real issue.

    Incidentally, in LLInitialize(), you want to check whether malloc() returned NULL before you make use of *list.
    I am checking this in the debugger, I have that information. This code is meant to help me figure out some things fast, so a couple of if .. else statements are not an advantage since they bring nothing new to the table.
    Last edited by rire1979; 12-21-2009 at 08:31 PM. Reason: clarification

  5. #5
    Registered User
    Join Date
    Dec 2009
    Posts
    5
    Why do you have an initialize function? Why aren't you just reusing your create node function?

    Quzah.
    LinkedList and Node are different structures. It's a stylistic choice.

  6. #6
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Quote Originally Posted by rire1979
    Inside LLCreateNode() address returned by malloc is (struct Node *) 0x100100090.

    Outside LLCreateNode() the value received by tmp is: 0x100090.
    This just convinces me that you're not properly including headers (or at least not properly prototyping). 0x100100090 is too large to fit into 32 bits, and, surprise surprise, when it is converted to a 32-bit value, it becomes 0x100090. Odds are it passed through an int on the way to tmp. Did you use -Wall, as I mentioned? Although I would expect gcc to complain about assigning the return value of an improperly prototyped LLCreateNode() to a pointer type, even without -Wall.

    At any rate, assuming your debugger is right, it seems that your pointer is being squeezed through somewhere too small at some point. Odds are it's because you forgot a prototype, but it's hard to be certain without seeing all the code.

  7. #7
    Registered User
    Join Date
    Dec 2009
    Posts
    5
    Quote Originally Posted by cas View Post
    This just convinces me that you're not properly including headers (or at least not properly prototyping). 0x100100090 is too large to fit into 32 bits, and, surprise surprise, when it is converted to a 32-bit value, it becomes 0x100090. Odds are it passed through an int on the way to tmp. Did you use -Wall, as I mentioned? Although I would expect gcc to complain about assigning the return value of an improperly prototyped LLCreateNode() to a pointer type, even without -Wall.

    At any rate, assuming your debugger is right, it seems that your pointer is being squeezed through somewhere too small at some point. Odds are it's because you forgot a prototype, but it's hard to be certain without seeing all the code.
    That is right. I didn't have all the function prototypes in the .h file. I had wrongly declared them in the .c file instead. That worked in such a way that it made the compiler assign the default return type to the LLCreateNode() function which is an int.

    There was a warning about a conversion from an int to a pointer type which along with your comments sent me in the right direction. Thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory Fragmentation with Dynamic FIFO Queue
    By fguy817817 in forum Linux Programming
    Replies: 17
    Last Post: 10-31-2009, 04:17 AM
  2. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  3. Allocate memory inside allocated memory block?
    By Heidi_Nayak in forum C Programming
    Replies: 14
    Last Post: 04-15-2009, 04:19 PM
  4. stack vs heap memory allocation
    By gongchengshi in forum C Programming
    Replies: 9
    Last Post: 11-18-2007, 12:17 PM
  5. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM