2

I came across some C++ code from a blog. I tested the code in my IDE. The function in the code can work properly even without the return statement in the recursion calls(the search(head->lchild, x) and the search(head->rchild, x)); Can anyone explain why?

Node* search(Node* head, int x){
      if(head == NULL) return NULL;
      else if(x == head->key) return head;
      else if(x <= head->key) search(head->lchild, x);
      else search(head->rchild, x);
}
wszdwp
  • 25
  • 4

2 Answers2

3

Your code has undefined behavior, so anything could happen, including doing what you intended. Under Clang, you don't get the result you expected.

I made minimal modifications to get your code to compile and exercise the path with undefined behavior:

struct Node { int key; Node *lchild; Node *rchild; };
Node *search(Node *head, int x){
  if(head == nullptr) return nullptr;
  else if(x == head->key) return head;
  else if(x <= head->key) search(head->lchild, x);
  else search(head->rchild, x);
}
Node a { 0, nullptr, nullptr };
Node b { 1, &a, nullptr };
int main() { search(&b, 0); }

Clang warns on your code by default, and causes your code to crash when it falls off the end of the function at -O0:

$ clang++ -std=c++11 wszdwp.cpp
wszdwp.cpp:7:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^
1 warning generated.
$ ./a.out
zsh: illegal hardware instruction (core dumped)  ./a.out

With Clang's -fsanitize=undefined, I get this:

$ clang++ -std=c++11 -w -fsanitize=undefined wszdwp.cpp && ./a.out
wszdwp.cpp:2:7: runtime error: execution reached the end of a value-returning function without returning a value

The code was probably working for you because your compiler "helpfully" put in a ret instruction at the end of the body of the function (without filling in the return value reigster, so the return value is likely to be inherited from the previous function you called).

Richard Smith
  • 13,696
  • 56
  • 78
1

Defining a non void function without a return statment has an Undefined Bihavour and the same think with a return statment without expression.

The C++11 says in § 6.6.3:

6.6.3 The return statement

2 A return statement with neither an expression nor a braced-init-list can be
used only in functions that do not return a value, that is, a function with
the return type void, a constructor (12.1), or a destructor (12.4).

...

Flowing off the end of a function is equivalent to a return with no value;
this results in undefined behavior in a value-returning function.

You have to turn on warnings in your compiler:

g++ -Wall

And you will get the error:

warning: no return statement in function returning non-void [-Wreturn-type]
 }
 ^
rullof
  • 7,124
  • 6
  • 27
  • 36