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]

Possible code generation bug using virtual destructors


IDE Netbeans 7.2
GDB: 7.3.50.20111026-cvs (cygwin-special)
GCC:  4.5.3 (for cygwin)

Assembly language and register values included as an attachment. Each section is 
separated by '========'. There are are five section; {1} operator new() source 
code, given below, {2} disassembly of code when a virtual base class destructor 
is used; (3) register values immediately before the failure; (4) disassembly of 
code when a virtual base class destructor is not used; (5) register values 
before the final call.


I have a direct call to a concrete destructor (delete header) in a derived 
class. The code generated when the base class constructor is virtual is 
different then when the base class destructor is not virtual. The code generated 
fails when the base class destructor is virtual and works correctly when the 
base class destructor is not virtual.

Without going into too much detail, I am reimplementing Weizenbaum's SLIP in 
C++. I use my own memory allocator. When memory is deleted it is put at the end 
of a list of available space. Allocation is from the front of the available 
space list. A sublist contains a pointer to the header of a list. During 
allocation when the allocated space refers to a sublist then the associated 
header contained in the sublist is deleted. The failure occurs in the inline 
code associated with 'delete header'. Assembly language 'call' statement used 
register eax which contains a zero, generating a fault on the call.

It is quite possible that I haven't implemented or understood the  care and 
feeding of virtual destructors. But a single line change  causing this type of 
damage is baffling, and all the non-sublist deletes  seem to work correctly. 
Sigh.

If I haven't said things  correctly or if the things said are muddled and lack 
reason, please correct me, don't punish me.

The base class destructor is ~SlipCell() { } in the base class header file.

The allocation code in the file SlipCell.cpp is; "operator new(size_t size);
    void * SlipCellBase::operator new(size_t size) {    // Create a new SLIP 
cell
       SlipCellBase* link;
       do  {
         if (avsl.top == NULL) {
            SlipCellBase::getAVSLSpace();
         }
         link = (SlipCellBase*)avsl.top;
         avsl.top = avsl.top->rightLink;
         avsl.avail--;
       } while((long)link == TEMPORARY );
       SlipOp* op = *(SlipOp**)link->getOperator();
       if (op->isSublist()) {
          SlipHeader* header = *(SlipHeader**)getSublistHeader(*link);
          cout << link->dump() << endl
                  << header->dump() << endl << flush;
          delete header; // <== point of failure
       }
       
           /* Zero Cell */
       link->setOperator((void*)undefinedOP);
       link->rightLink = link->leftLink = (SlipCellBase*)UNDEFDATA;
       link->resetData();
       return link;
    }; // void * SlipCellBase::operator new(size_t size)

The inline delete method in the file SlipHeader.h is:


         ~SlipHeader() { deleteHeader(); }; // ~SlipHeader()

         void deleteHeader() {
            if (*(getHeadRefCnt()) <= 1) {
               addAVSLCells( this             // pointer to first cell
                           , getLeftLink());  // pointer to last cell
            } else 
               *(getHeadRefCnt()) -= 1;
         }; // void deleteHeader()

Attachment: disasembly.txt
Description: Text document


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