2

GCC generates the wrong instructions when I write a function which returns a reference to a local variable. I know perfectly that you shouldn't do that.

Here is the simple Code:

#include <stdio.h>
#include <stdlib.h>

int *func()
{
    int a = 100;
    return &a;
}

int main()
{
    printf("%p\n", func());
}

The output of the program is "(nil)".

I just compiled this with "gcc sample.c" and disassembled the executable with gdb:

Dump of assembler code for function func:
   0x00000000004004e6 <+0>: push   %rbp
   0x00000000004004e7 <+1>: mov    %rsp,%rbp
   0x00000000004004ea <+4>: movl   $0x64,-0x4(%rbp)
   0x00000000004004f1 <+11>:    mov    $0x0,%eax
   0x00000000004004f6 <+16>:    pop    %rbp
   0x00000000004004f7 <+17>:    retq   
End of assembler dump.
Dump of assembler code for function main:
   0x00000000004004f8 <+0>: push   %rbp
   0x00000000004004f9 <+1>: mov    %rsp,%rbp
   0x00000000004004fc <+4>: mov    $0x0,%eax
   0x0000000000400501 <+9>: callq  0x4004e6 <func>
   0x0000000000400506 <+14>:    mov    %rax,%rsi
   0x0000000000400509 <+17>:    mov    $0x4005a4,%edi
   0x000000000040050e <+22>:    mov    $0x0,%eax
   0x0000000000400513 <+27>:    callq  0x4003c0 <printf@plt>
   0x0000000000400518 <+32>:    mov    $0x0,%eax
   0x000000000040051d <+37>:    pop    %rbp
   0x000000000040051e <+38>:    retq   
End of assembler dump.

As you can see the return value is 0. It should be -0x4(%rbp). I've found nothing which this explains. My guess was that the GCC developers wanted that this code fails as fast as possible (null pointer dereferencing) but this couldn't be. A compiler has to generate the right instructions. I've tested this with GCC 5.3.0.

  • 5
    I don't think there _exist_ right instructions for this case; it's an act that leads to Undefined Behaviour, meaning that the compiler can generate whatever instructions it wants to. – Williham Totland May 01 '16 at 14:42
  • 1
    Or of https://stackoverflow.com/questions/4570366/pointer-to-local-variable – larsks May 01 '16 at 14:43
  • And [a generally good write-up of undefined behavior](http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html) in C – larsks May 01 '16 at 14:44
  • 1
    A pointer to an object that no longer exists has *indeterminate value*. There's no "right" or "wrong" value here. This indeterminate value manifested itself as a null pointer in your experiment? Nothing wrong with it. – AnT stands with Russia May 01 '16 at 14:44
  • 1
    In my opinion this is still "wrong". If the programmer wanted the address then he wanted the **address** but I understand that it is not defined. Also this is **not** a duplicate because my question refers to the generated instructions and not to the fact that it is not defined. Why do you think I wrote "I know perfectly that you shouldn't do that."? – Benedikt Weiß May 01 '16 at 15:06
  • You may find this interesting: http://stackoverflow.com/questions/36472344/how-to-write-a-function-which-return-a-pointer-to-the-stack. Some people use your same construct to get useful functionality. I hope they don't get a null pointer. – atturri May 01 '16 at 15:36
  • 1
    'I want undefined behaviour to be defiined' #00327690234 :( – Martin James May 01 '16 at 15:46
  • @BenediktWeiß What you're doing here is undefined behaviour, the C standard does say that the compiler can do whatever it wants. The compiler could give you nasal daemons, or could halt compilation, or emit "wrong" instructions. You can't rely on the compiler having "defined" behaviour for such situations. – Leandros May 01 '16 at 15:47
  • I'm "doing" nothing. I just stumbled upon this because I wanted to know what happens **if** I do that. I'm an experienced programmer. I was just surprised that the GCC generates **these** specific instructions because I thought the GCC people were more like "we wont stop him if he does that" and not so "patronising". So yeah: it is just undefined, thank you for your time ;-) – Benedikt Weiß May 01 '16 at 20:03

1 Answers1

5

The compiler has generated the right instructions. What you are doing is not defined by the C standard, so the compiler is free to do whatever it pleases. In this case it seems that GCC pleases to return a null pointer, probably so that your program will fail as fast as possible.

David Seiler
  • 9,557
  • 2
  • 31
  • 39