I ran into a very weird problem today. Long story short, my function returns one value, the caller gets a different value. Somewhere around my code I have a call to:
Message* m = NULL;
m = connection_receive(c);
Where connection_receive is defined as follows:
Message* connection_receive(Connection* c)
{
Message* k;
if (c->state == CON_STATE_AUTHENTICATED)
{
pthread_mutex_lock(&c->mutex_in);
if (g_queue_is_empty(c->in))
k = NULL;
else
k = (Message*)g_queue_pop_head(c->in);
pthread_mutex_unlock(&c->mutex_in);
/* Until here, k is reachable and contains the correct data. */
return k;
}
else
return NULL;
}
Here's a gdb run, I stopped right before the return and right after the assignment:
222 return k;
(gdb) p k
$1 = (Message *) 0x7ffff0000950
(gdb) n
226 }
(gdb) n
main () at src/main.c:57
57 if (m)
(gdb) p m
$2 = (Message *) 0xfffffffff0000950
Of course, if we try to access 0xfffffffff0000950 we'll get a segmentation fault.
If I change the function and instead of returning a value, using a second parameter to pass the value it works, but I would like to know what went wrong on this one.
Thank you very much.
EDIT: This works, but it's not convenient. And I would also like to know why such strange error is happening.
void connection_receive2(Connection* c, Message** m)
{
if (c->state == CON_STATE_AUTHENTICATED)
{
pthread_mutex_lock(&c->mutex_in);
if (g_queue_is_empty(c->in))
*m = NULL;
else
*m = (Message*)g_queue_pop_head(c->in);
pthread_mutex_unlock(&c->mutex_in);
}
else
*m = NULL;
}
EDIT2: Solved. Thanks all. The problem was a typo on the header file. I can't use -Werror because I need to do things which raise some warnings, and in a large make output and large header I missed it.
The return value is stored in registers - on x64 it goes in RAX. On x86, 64-bit structures like DateTime are returned in EAX:EDX. In the example, there is a method AddFive. Its return value goes to the end of stack (because Int32 is a value type), the same way as it works in C/C++, there is no big difference.
A function returns the address of a stack variable, which will cause unintended program behavior, typically in the form of a crash. Because local variables are allocated on the stack, when a program returns a pointer to a local variable, it is returning a stack address.
In C there are no subroutines, only functions, but functions are not required to return a value. The correct way to indicate that a function does not return a value is to use the return type "void". ( This is a way of explicitly saying that the function returns nothing. )
What is stack overflow? A stack overflow is a type of buffer overflow error that occurs when a computer program tries to use more memory space in the call stack than has been allocated to that stack.
m
defined?I suspect that there is a mismatch with the types and that my question 2 is the crux of all.
You are returning a pointer with (I suppose so) 48 or 64 bits. The caller, however, thinks to get a int
, which has maybe 32 bits and is signed. On converting back to a pointer, the value gets sign-extended.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With