开发者

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

开发者 https://www.devze.com 2023-02-19 01:52 出处:网络
The following code works fine: typedef struct node_s { void *data; struct node_s *next; } NODE; typedef struct test_s

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)
{
开发者_如何学Go    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!


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.


The reason it works on most of the systems is that stack is not zeroed out when the frame is popped. If you make a small seemingly unrelated change to your program, it will stop working.

int junk()
{
    char junkdata[100] = {0};
    return 42;
}

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

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

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

This happens because junk() overwrites the structure on stack with zeros.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号