Jump to content
  • Advertisement
Sign in to follow this  
zaerl

This snippet can't run

This topic is 4081 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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:
#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 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?

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites
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";
}

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.



Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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;
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!