Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C function change value on return. Corrupted stack?

Tags:

c

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.

like image 858
Victor Avatar asked Nov 06 '11 18:11

Victor


People also ask

Is return value stored in stack?

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.

Can a function return a stack?

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.

Why is my function not returning a value in C?

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 does stack overflow*?

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.


1 Answers

  1. How is your m defined?
  2. Has your caller access to the right prototype?
  3. What architecture are you on?

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.

like image 173
glglgl Avatar answered Oct 05 '22 10:10

glglgl