2
typedef struct person {
    int id;
    char* name;
} Person;

//constructor like function
Person* New_Person(int id,char *name){
    Person* p = malloc(sizeof(Person));
    p->id = id;
    p->name = name;
    //return p; 
}

int main(){
    for(int i=0;i<10;i++){
        Person* p = New_Person(i,"abcd");
        printf("id:%d name:%s \n",p->id,p->name);
    }
    printf("DONE\n");
    return 0;
}

New_Person is like a constructor and its supposed to return a pointer to the newly allocated person, if i comment the return statement in the New_Person function i still get the same behavior, can someone please explain to me why it compiles and gives the same behavior without a return statement?

FPGA
  • 3,525
  • 10
  • 44
  • 73
  • You are just lucky since you are getting expected output by having undefined behavior in your code. I doubt how the compiler is not throwing warning that you are not returning from the function.. – Gopi Mar 05 '15 at 14:14
  • @Gopi i really don't get it i forgot the return statement by accident and it still worked – FPGA Mar 05 '15 at 14:15
  • 3
    possible duplicate of [Function returns value without return statement](http://stackoverflow.com/questions/4644860/function-returns-value-without-return-statement) – Anto Jurković Mar 05 '15 at 14:25
  • 2
    Look for "undefined behavior". It means, anything can happen, and a compiler doesn't need to tell you. Using the return value of a function which doesn't return is undefined. Using proper warning settings catches some instances (`-Wall` does here, with gcc, for example). – mafso Mar 05 '15 at 14:28
  • 1
    @mafso thanks for the -Wall now i am getting a warning – FPGA Mar 05 '15 at 14:33

2 Answers2

4

What you have is undefined behavior.

The pointer p within main() is never initialized without return from function New_person(). So using uninitialized variable lead to undefined behavior.

You are allocating some memory on heap and the address returned by malloc() is never known to the pointer p within main(). So you are accessing some random memory and for your luck the random memory is the one allocated by you on heap.

Gopi
  • 19,784
  • 4
  • 24
  • 36
1

I got the same behavior, so I disassembled your constructor:

0000000000000000 <New_Person>:
 0: 55                      push   %rbp
 1: 48 89 e5                mov    %rsp,%rbp
 4: 48 83 ec 20             sub    $0x20,%rsp
 8: 89 7d ec                mov    %edi,-0x14(%rbp)
 b: 48 89 75 e0             mov    %rsi,-0x20(%rbp)
 f: bf 10 00 00 00          mov    $0x10,%edi
14: e8 00 00 00 00          callq  19 <New_Person+0x19>
19: 48 89 45 f8             mov    %rax,-0x8(%rbp)
1d: 48 8b 45 f8             mov    -0x8(%rbp),%rax
21: 8b 55 ec                mov    -0x14(%rbp),%edx
24: 89 10                   mov    %edx,(%rax)
26: 48 8b 45 f8             mov    -0x8(%rbp),%rax
2a: 48 8b 55 e0             mov    -0x20(%rbp),%rdx
2e: 48 89 50 08             mov    %rdx,0x8(%rax)
32: c9                      leaveq 
33: c3                      retq   

Looks like your pointer is being stored in the rax register which happens to be the register where function return values are stored (for integer and pointer types).

eduffy
  • 39,140
  • 13
  • 95
  • 92