¿Por qué el método de llamada a través del puntero nulo "funciona" en C++? [duplicar]

Posible duplicado:
Llamar al método de clase a través del puntero de clase NULL

#include <iostream>
using namespace std;
class test
    int i;
    test():i(0){ cout << "ctor called" << endl;}
    void show()
        cout<<"show fun called"<<endl;

int main(int argc , char *argv[])
    test *ptr = NULL;
    return 0;

clearly, no ctor will be called. Is this standard? or just some compiler optimization as this pointer is not used in show() member function?

preguntado el 04 de julio de 12 a las 01:07

Dereferencing a null pointer is UB. -

Añada i = 1; dentro show() and try to run it. -

chris, UB means up to compiler implementation? and I am using g++ 4.6.3. Jesse Good, of course, seg fault, there is no doubt. I am wondering if compiler will generate code without this for member function which does not need it. -

@bbc: UB means "undefined behavior", which is different than "implementation defined". Implementation defined means that the behavior is at least defined, though that definition may vary between compilers. Also; "of course, seg fault, there is no doubt." - Actually, there is a ton of doubt, because the behavior is indefinido. If it were sure to cause a segfault then it would be perfectly well defined, which it is not. Anything can happen, though in practice a segfault is likely (you hope). -

Your code is valid under most compilers [No crashing on GCC and MSVC here]. Luckily, your show() method qualifies as pure STATIC. you are not DEREFERENCING the pointer! Function Call on Pointer to non-polymorphic class does NOT dereference the pointer. It merely CALLs the Address of the method with stack frame in which this pointer is zeroed. If your code then only uses global variables and never touches this pointer - or the non-static data members - you are okay. Touching the static data members is also okay. Better, just mark your method static and forget about the pointer! -

4 Respuestas

The pointer isn't needed to call the method. The type of the pointer is known, so the code for the method is known. The method doesn't use this, so it runs the code just fine. It's undefined behavior, but its more efficient not to check if the pointer is NULL, so it runs.

Respondido 04 Jul 12, 01:07

(How) would a virtual method affect his observed behavior? - user166390

I would expect a virtual method call to fail, since it needs to look up the method in the vtable, which it would find at the other end of the pointer, but the pointer is NULL. - Ned Batchelder

seg fault for virtual with g++, not sure this is also implementation dependent. will compiler generate vptr and vtblr without object of class? guess not for efficiency reason? - BBC

Classic non-virtual methods are called directly with asm call. The stack frame then has this pointer zeroed. Virtual methods however will most-likely segfault because the pointer must be dereferenced. - Петър Петров

If you look at the assembly (for at least one compiler), you can see why it runs (even though it is undefined behavior as many have pointed out). For these two lines:

test *ptr = NULL;

This assembly is generated (in one compiler I just tried):

00000004: C7 45 FC 00 00 00  mov         dword ptr [ebp-4],0
0000000B: 8B 4D FC           mov         ecx,dword ptr [ebp-4]
0000000E: E8 00 00 00 00     call        ?show@test@@QAEXXZ

It pushes the NULL (0) on the stack and calls the method since the address of the method is independent of the actual object instance.

Respondido 04 Jul 12, 01:07

It is not valid, the behavior is undefined and actual results depended on your compiler.

Respondido 04 Jul 12, 01:07

Well, it's valid. __thiscall function that does not access this pointer is just a static function. Just add "static" - it is the best you can do in code that is static by definition :) And it forces the function to use __cdecl, so no this pointer requirement. Note that adding virtual will then make more complicated preparation that requires dereferencing the pointer, and will then segfault. - Петър Петров

Well, first off, it's not valid as it invokes undefined behavior. You are really asking why the compiler allows it, and the answer is because that is boneheaded code that simply won't occur in a real application, so why bother? The real problem comes when the pointer is made invalid en tiempo de ejecución in a way that cannot be anticipated by static code analysis.

The compiler is not there to hold your hand, it is there to compile your code according to the standard. If it offers useful warnings then great, but there is nothing syntactically or semantically illegal there, you are simply writing code which causes undefined behavior.

Respondido 04 Jul 12, 01:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.