Search code examples
cstructheap-memorypass-by-valuestack-memory

Local struct stored in a global linked list (and accessed in other functions) works in VC2010. Is this correct C99/ANSI?


The following code works fine:


typedef struct node_s {
    void *data;
    struct node_s *next;    
} NODE;

typedef struct test_s
{
    int asdf;
}TEST;
NODE *list_create(void *data)
{
    NODE *node;
    if(!(node=malloc(sizeof(NODE)))) return NULL;
    node->data=data;
    node->next=NULL;
    return node;
}

NODE *list_insert_after(NODE *node, void *data)
{
    NODE *newnode;
    newnode=list_create(data);
    newnode->next = node->next;
    node->next = newnode;
    return newnode;
}

NODE *list, *second, *third;

void localstructtest()
{
    TEST t;
    t.asdf = 10;

    third = list_insert_after(second, (void*)&t);
}

int main()
{
    TEST th;
    TEST* hrm;

    /* Create initial elements of list */
    list=list_create((void*)"First");
    second=list_insert_after(list, (void*)"Second");
    localstructtest();

    hrm = (TEST*)third->data;
    th = *hrm;
    return 1;
}

The struct is created locally in a function other than main, yet I was able to retrieve the data from the linked list outside of the scope of localstructtest(). Local variables are created on the stack, is this true with this struct as well? Or is it actually created on the heap and the pointer/reference remains valid? I expected this to fail horribly when I tested it. I'll admit that I am a C++ programmer and I probably don't completely understand the ramifications of there being no pass-by-reference in C. If it is OK to use the struct data like this, when does the data ever get freed?

Thanks!


Solution

  • Undefined behavior. It may work, it may not, it may turn your computer into a warthog, all depending on the phase of the moon.

    Seriously: this may work in a small example program, but it's sure to blow up in your face as the program grows.

    As for pass-by-reference: in C you'd do that by passing a pointer. The basic memory allocations rules are the same as in C++: a local struct is allocated on the stack and destroyed when it goes out of scope. The main difference is that there's never a destructor, so you can't get full RAII.