#include <iostream>
namespace
{
struct foo
{
void bar() const
{
std::cout << "hi there\n";
}
};
template<class T> class not_so_smart_ptr
{
public:
T* operator->() const
{
return 0;
}
};
}
int main(int argc, char* const argv[])
{
not_so_smart_ptr<foo> test;
test->bar(); // <---- this can't be
return 0;
}
This snippet can't run
Today I was playing a little with smart pointers. I've accidentally written a wrong line of code. I have extrapolated the line from the main program:
This snippet really print "hi there" but:
*) operator-> return 0. The program should spawn a segfault
*) bar() isn't static
*) bar() isn't a not_so_smart_pointer method
I think that I really miss something. Tested on gcc 4.0.1 with command-line:
g++ -o test -Wall test.cpp
Someone can explain me?
Quote:
*) operator-> return 0. The program should spawn a segfault
No, it shouldn't. Correct standard-compliant behavior for dereferencing a null pointer is undefined behavior. It doesn't have to segfault. It's very common however, for compilers to generate code that works as you've observed in this scenario. The reason is because the function in question does not use the "this" pointer (which is the null pointer in question here), so the compiler has no need to generate an attempt to read memory at that location, and no reason to segfault.
This most likely removes the class altogeter (common with templates), resulting in your code being simply:
int main(int argc, char* const argv[]){std::cout << "hi there\n";}
Quite like jpetrie already wrote. I could point out an additional resource, Segmentation fault, from Wikipedia that elaborates this somewhat and explains further what is happening. The reason this is undefined behaviour is that it is operating system dependent. It is the operating system that decides what it should do when a program tries to access memory that is not in the allocated are for it.
[EDIT: undeclard -> undefined - I must be too tired already...]
[Edited by - Naurava kulkuri on July 23, 2007 1:10:47 PM]
[EDIT: undeclard -> undefined - I must be too tired already...]
[Edited by - Naurava kulkuri on July 23, 2007 1:10:47 PM]
Quote:Original post by Antheus
This most likely removes the class altogeter (common with templates), resulting in your code being simply:
*** Source Snippet Removed ***
That is what I see when I check the compiler output:
LC0: .ascii "hi there\12\0" .text
and
call ___main movl $__ZSt4cout, (%esp) movl $LC0, %eax movl %eax, 4(%esp)
This is called empty base class optimisation. In essence this means that the internal representation of a class does not require any bits of memory at run time. This is the case typically for classes that contain only type members, nonvirtual function members, and static data members. Nonstatic data members, virtual functions, and virtual base classes, on the other hand, do require some memory at run time.
Anyway, if you try to print the size of that class with sizeof you probably get 1 as the answer. If your system imposes more strict aligment restrictions, it probably prints out 4. There is a great book regarding templates called C++ Templates: The Complete Guide by Nicolai M. Josuttis and David Vandevoorde.
Yes I know about the "undefined behaviour" but usually it's a segfault cause the program try to access to a block of memory that it can't access but it's not the point. On my system sizeof(not_so_smart_ptr<foo>) is 1.
The really thing I do not understand is that not_so_smart_ptr is a template and it cannot has the method "bar()". It's a method of the parameterized type "struct foo". Other than this operator-> do not returns a valid pointer.
I really do not understand.
The really thing I do not understand is that not_so_smart_ptr is a template and it cannot has the method "bar()". It's a method of the parameterized type "struct foo". Other than this operator-> do not returns a valid pointer.
I really do not understand.
Quote:Original post by zaerl
The really thing I do not understand is that not_so_smart_ptr is a template and it cannot has the method "bar()". It's a method of the parameterized type "struct foo". Other than this operator-> do not returns a valid pointer.
I really do not understand.
Maybe breaking things apart will help explain.
The original program:int main(int argc, char* const argv[]){ not_so_smart_ptr<foo> test; test->bar(); return 0;}This is the same (equivilant):int main(int argc, char* const argv[]){ not_so_smart_ptr<foo> test; foo* temp1 = test.operator->(); //note: temp1 == 0 temp1->bar(); //note: foo::bar() never dereferences "this" (aka temp1) internally, hence no crash. // if foo::bar... // ...were virtual // ...used a member variable // ...dynamic_cast<...>(this)ed // ...used any function that did one of the above // then it would probably crash. return 0;}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement