开发者

Nested calls can lead to uninitialized arguments in C?

开发者 https://www.devze.com 2022-12-17 02:08 出处:网络
Is len correctly initialized and safe in set_array call? void object_copy (Object* self, Object* obj) {

Is len correctly initialized and safe in set_array call?

void object_copy (Object* self, Object* obj) {
    int len;
    object_set_array (self, object_get_array (obj, &len), len);
}

If n开发者_StackOverflow中文版ot, what would you recommend?


No - there's no defined order of evaluation for arguments to a function call.

Even though the call to object_get_array() has to occur before the call to object_set_array(), the value that the compiler calculates and passes to object_set_array() for the len parameter can be done before the compiler makes the call to object_get_array().

I'm not sure what the 2nd parameter to the object_set_array() call is intended to be - maybe you wanted to use the comma operator:

void object_foo (Object* self, Object* obj) {
    int len;

    object_set_array (self, (object_get_array (obj, &len), len));
}

Which would work, but is confusing and something I wouldn't recommend.

I think what you want is:

void object_foo (Object* self, Object* obj) {
    int len;

    object_get_array (obj, &len);  // get the length from obj

    object_set_array (self, len)); // set the len for self
}


No. The third parameter of object_set_array() might be evaluated and pushed onto the stack before the second parameter (object_get_array()) is evaluated.

Probably you want

void object_copy (Object* self, Object* obj) {
    int len;
    /* I'm just guessing as to the return type */
    Object *pObj = object_get_array(obj, &len); 
    object_set_array (self, pObj, len);
}


You are passing len by value into the object_set_array() call before it is initialized. So that is wrong and a good compiler will warn about that. The variable will contain a random value, so the code will not crash, but it won't do what you probably want.


If object_get_array fails, then len may not get initialized. It would be better call object_get_array first before calling object_set_array, in that way you could test if the call worked or not.

Here's an example code, note that I do not know what object_get_array returns so I have used a void * to make it easier to explain:

void *obj;
obj = object_get_array(obj, &len);
if (obj != NULL) object_set_array(self, obj, len);

The code that you have written is dangerous, but resorting to shortcuts like this could lead you to think that object_set_array has failed and not object_get_array. You have to judge for yourself if it will fail or not, I always assume the code fails so that I can put safeguards in place, your approach will be different, certain shortcuts are ok, this one isn't!

Even though, C code is executed from left to right, in the order of how the expression is evaluated (depends on the compiler and compiled code), if the function worked, then yes, len would be initialized, but it is not safe.

Hope this helps, Best regards, Tom.


This will also work:

ARRAY object_get_array (Object* self, int* len);
void object_set_array (Object* self, ARRAY array, const int* len);

// ...

void object_copy (Object* self, Object* obj) {
    int len;
    object_set_array (self, object_get_array (obj, &len), &len);
}

because the call to object_get_array() will always be evaluated before the call to object_set_array(), at which point len will have been set to the correct value.

0

精彩评论

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