Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird behavior with a manually defined strlen

Accidentally, I wrote the following interesting snippet:

#include <iostream>
#include <cstring>

size_t strlen(const char* str) {
    std::cout << "hello";
    return 0;
}

int main() {
    return std::strlen("sdf");
}

Unexpectedly for me, the output is "hello" in GCC 5.1, which means that my strlen is being called. Even more interesting, if I remove the return, i.e. replace main with just a call of std::strlen("sdf");, nothing gets printed!

I also tried Clang, for which std::strlen calls the real function which calculates the string length (and nothing gets printed). That's what I expected to see.

How can this be explained? Is defining my own strlen function considered undefined behavior?

like image 328
Paul Avatar asked Jan 19 '17 16:01

Paul


2 Answers

There is nothing interesting here, just a function overload and a bit of undefined behavior. You overloaded the library function strlen() with your own version. Since in GCC implementation of std::strlen is nothing but a library function call inside namespace std, you get the result you are seeing.

Here is relevant extract from cstring:

namespace std _GLIBCXX_VISIBILITY(default)
{
 _GLIBCXX_BEGIN_NAMESPACE_VERSION

  using ::strlen;
  ...

And when you remove the return statement, GCC optimizes away the call altogether, as it knows that strlen is function without side-effects, and it is actually a reserved name, which should not be overloaded. I assume, compiler might give you a warning here, but alas, it didn't, as it is not required to.

like image 69
SergeyA Avatar answered Nov 10 '22 15:11

SergeyA


According to C++14 [extern.names]/3, ::strlen is reserved:

Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.

and the effect of using a reserved name, [reserved.names]/2:

If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by this Clause, its behavior is undefined.

So your program has undefined behaviour.

like image 4
M.M Avatar answered Nov 10 '22 14:11

M.M