This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Run-time error with virtual function w/o invocation


Arthur Schwarz <aschwarz1309@att.net> writes:

> I ran the compiler from the shell (g++ -pedantic main.cpp) without any errors or 
> warnings and with the same results. I don't think that the method 'new' is in 
> error. The segmentation fault does not occur unless the virtual function, fnc, 
> is uncommented. If 'fnc' is commented, 'new' executes correctly. I think that 
> this might be a compiler bug, but before I waste anyone's time I thought I'd get 
> validation that I'm not doing some dumb ol' thing.

The bug is in your program, as g++-4.7 -Wall warns:

main.cpp: In static member function âstatic void* baseClass::operator new(size_t)â:
main.cpp:7:76: warning: no return statement in function returning non-void [-Wreturn-type]

If you fix that, e.g. by adding "return ::operator new(size);",
then the program will not crash even if you uncomment the virtual
functions.

With the buggy baseClass::operator new, why does it matter
whether the classes have virtual functions?  It's because GCC
implements virtual functions by adding a vtable pointer to each
instance of the class.  The constructors of baseClass and
inheritClass then initialize the vtable pointer.  Because
baseClass::operator new returned something bogus, the "this"
pointer is bogus in these constructors, and they write to some
memory location where they shouldn't.  Judging from the assembly
code generated by GCC, it seems likely that the "this" pointer
points to the std::cout object, which then becomes corrupted and
causes the program to crash.

If you comment out the virtual functions, then there is no vtable
pointer that the constructors would have to initialize.  Because
your constructors don't initialize any data members either, they
don't write to the baseClass or inheritClass object that is being
constructed at the bogus address, thus avoiding the crash.  It
would surely be unwise to rely on such behaviour though.

You can get a similar crash even without virtual functions:

===============================================================================
#include <iostream>

using namespace std;

class baseClass {
public:
   /* buggy code for demonstration purposes */
   static void* operator new(size_t size) { cout << "new" << endl << flush;}
   int x;
   baseClass()  { x = 1; cout << "baseClass constructor" << endl << flush;}
};

int main() {
   new baseClass();
   return 0;
}
===============================================================================

Here, if you remove the x = 1 assignment, it avoids the memory
corruption and the crash, although operator new still won't be right.

Attachment: pgp00000.pgp
Description: PGP signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]