Reputation: 385
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.
Upvotes: 8
Views: 2713
Reputation: 1
We faced the same problem and the root cause was the implicit declaration of the function connection_receive(). So it was defaulted to int which signed and then stored in m.
Upvotes: 0
Reputation: 36102
Did you push a malloc:ed object on the queue? If not and you instead pushed a stack object then when you may end up with weird behavior when you pop items.
Upvotes: 0
Reputation: 91099
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.
Upvotes: 6