How does returning values from a function work?

2019-02-13 19:19发布

I recently had a serious bug, where I forgot to return a value in a function. The problem was that even though nothing was returned it worked fine under Linux/Windows and only crashed under Mac. I discovered the bug when I turned on all compiler warnings.

So here is a simple example:

#include <iostream>

class A{
public:
    A(int p1, int p2, int p3): v1(p1), v2(p2), v3(p3)
    {
    }

    int v1;
    int v2;
    int v3;
};

A* getA(){
    A* p = new A(1,2,3);
//  return p;
}

int main(){

    A* a = getA();

    std::cerr << "A: v1=" << a->v1 << " v2=" << a->v2 << " v3=" << a->v3 << std::endl;  

    return 0;
}

My question is how can this work under Linux/Windows without crashing? How is the returning of values done on lower level?

标签: c++ stack
8条回答
叼着烟拽天下
2楼-- · 2019-02-13 19:44

As Kerrek SB mentioned, your code has ventured into the realm of undefined behavior.

Basically, your code is going to compile down to assembly. In assembly, there's no concept of a function requiring a return type, there's just an expectation. I'm the most comfortable with MIPS, so I shall use MIPS to illustrate.

Assume you have the following code:

int add(x, y)
{
    return x + y;
}

This is going to be translated to something like:

add:
    add $v0, $a0, $a1 #add $a0 and $a1 and store it in $v0
    jr $ra #jump back to where ever this code was jumped to from

To add 5 and 4, the code would be called something like:

addi $a0, $0, 5 # 5 is the first param
addi $a1, $0, 4 # 4 is the second param
jal add
# $v0 now contains 9

Note that unlike C, there's no explicit requirement that $v0 contain the return value, just an expectation. So, what happens if you don't actually push anything into $v0? Well, $v0 always has some value, so the value will be whatever it last was.

Note: This post makes some simplifications. Also, you're computer is likely not running MIPS... But hopefully the example holds, and if you learned assembly at a university, MIPS might be what you know anyway.

查看更多
三岁会撩人
3楼-- · 2019-02-13 19:44

When popping values from the stack in IBM PC architecture there is no physical destruction of the old values ​​of data stored there. They just become unavailable through the operation of the stack, but still remain in the same memory cell.

Of course, the previous values ​​of these data will be destroyed during the subsequent pushing of new data on the stack.

So probably you are just lucky enough, and nothing is added to stack during your function's call and return surrounding code.

查看更多
登录 后发表回答