Nested calls can lead to uninitialized arguments in C?
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.
精彩评论