This is the mail archive of the gcc-bugs@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]

[Bug c++/22446] New: Invocation of destructor of element of array changes vtable


Say B is a subclass of A.  I create an compile time array of 10 objects of type
B and invoke the destructor on each member of the array.  Afterwards, the vtable
pointer for each element of B is to instances of A.

This came up with a template collection class that is a combination of vector
and a compile time allocator of fixed length to have better performance with
short lists.

I boiled the problem down to just a compile time allocation of the array and
that is the code attached here.  I had trouble attaching the .ii file because of
its length.  I will attach the source file which just has an include of
<iostream> before the .ii file.

Gcc Version: 3.4.3 (also 3.2.2 on 32 bit intel platform)

platform: Linux AMD 64 bit (also 32 bit intel i686 running RedHat 9.0)

O/S: Red Hat Enterprise Linux AS release 4 (Nahant)

(also RedHat 9.0)

Compiler warnings and output: none

Build options: Default

Command line and result:

g++ -v -save-temps test_compbug2.C
Reading specs from /usr/lib/gcc/x86_64-redhat-linux/3.4.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--disable-checking --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-languages=c,c++,objc,java,f77
--enable-java-awt=gtk --host=x86_64-redhat-linux
Thread model: posix
gcc version 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)
 /usr/libexec/gcc/x86_64-redhat-linux/3.4.3/cc1plus -E -quiet -v -D_GNU_SOURCE
test_compbug2.C -mtune=k8 -o test_compbug2.ii
ignoring nonexistent directory
"/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../x86_64-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3
 /usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/x86_64-redhat-linux
 /usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/backward
 /usr/local/include
 /usr/lib/gcc/x86_64-redhat-linux/3.4.3/include
 /usr/include
End of search list.
 /usr/libexec/gcc/x86_64-redhat-linux/3.4.3/cc1plus -fpreprocessed
test_compbug2.ii -quiet -dumpbase test_compbug2.C -mtune=k8 -auxbase
test_compbug2 -version -o test_compbug2.s
GNU C++ version 3.4.3 20041212 (Red Hat 3.4.3-9.EL4) (x86_64-redhat-linux)
        compiled by GNU C version 3.4.3 20041212 (Red Hat 3.4.3-9.EL4).
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
 as -V -Qy -o test_compbug2.o test_compbug2.s
GNU assembler version 2.15.92.0.2 (x86_64-redhat-linux) using BFD version
2.15.92.0.2 20040927
 /usr/libexec/gcc/x86_64-redhat-linux/3.4.3/collect2 --eh-frame-hdr -m
elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../lib64/crt1.o
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../lib64/crti.o
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/crtbegin.o
-L/usr/lib/gcc/x86_64-redhat-linux/3.4.3
-L/usr/lib/gcc/x86_64-redhat-linux/3.4.3
-L/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../lib64
-L/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../.. -L/lib/../lib64
-L/usr/lib/../lib64 test_compbug2.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/crtend.o
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../lib64/crtn.o

Result of program:
In B's CompBugIt: 0 In A's CompBugIt: 0
In B's CompBugIt: 10 In A's CompBugIt: 1
In B's CompBugIt: 20 In A's CompBugIt: 2
In B's CompBugIt: 30 In A's CompBugIt: 3
In B's CompBugIt: 40 In A's CompBugIt: 4
In B's CompBugIt: 50 In A's CompBugIt: 5
In B's CompBugIt: 60 In A's CompBugIt: 6
In B's CompBugIt: 70 In A's CompBugIt: 7
In B's CompBugIt: 80 In A's CompBugIt: 8
In A's CompBugIt: 9
In A's CompBugIt: 8
In A's CompBugIt: 7
In A's CompBugIt: 6
In A's CompBugIt: 5
In A's CompBugIt: 4
In A's CompBugIt: 3
In A's CompBugIt: 2
In A's CompBugIt: 1

it should have been:

In B's CompBugIt: 0 In A's CompBugIt: 0
In B's CompBugIt: 10 In A's CompBugIt: 1
In B's CompBugIt: 20 In A's CompBugIt: 2
In B's CompBugIt: 30 In A's CompBugIt: 3
In B's CompBugIt: 40 In A's CompBugIt: 4
In B's CompBugIt: 50 In A's CompBugIt: 5
In B's CompBugIt: 60 In A's CompBugIt: 6
In B's CompBugIt: 70 In A's CompBugIt: 7
In B's CompBugIt: 80 In A's CompBugIt: 8
In B's CompBugIt: 90 In A's CompBugIt: 9
In B's CompBugIt: 80 In A's CompBugIt: 8
In B's CompBugIt: 70 In A's CompBugIt: 7
In B's CompBugIt: 60 In A's CompBugIt: 6
In B's CompBugIt: 50 In A's CompBugIt: 5
In B's CompBugIt: 40 In A's CompBugIt: 4
In B's CompBugIt: 30 In A's CompBugIt: 3
In B's CompBugIt: 20 In A's CompBugIt: 2
In B's CompBugIt: 10 In A's CompBugIt: 1

--------------- source file (.ii is so long hangs emacs) -------------------
#include <iostream>

class A
{
private:
    int a;
public:
    A(int iA=1) : a(iA) {}
    A(const A& iA) { *this = iA; }
    A& operator=(const A& iA) {
	if (this != &iA) {
	    a = iA.a;
	}
	return *this;
    }
    virtual ~A() {}
    virtual int GetA() const;
    void SetA(int iA) { a = iA; }
    virtual void CompBugIt() const;
    
    friend int operator==(const A& iA, const A& iB) {
	return (iA.a == iB.a);
    }
    
    friend int operator != (const A& iA, const A& iB) {
	return !(iA == iB);
    }
};

int A::GetA() const { return a; }

void A::CompBugIt() const
{
    std::cout << "In A's CompBugIt: " << a;
}

class B : public A
{
private:
    int b;
public:
    B(int iA=1, int iB=2) : A(iA), b(iB) {}
    B(const B& iB) : A() { *this = iB; }
    B& operator=(const B& iB) {
	if (this != &iB) {
	    A::operator=(iB);
	    b = iB.b;
	}
	return *this;
    }
    ~B() {}
    
    void CompBugIt() const;
};

void B::CompBugIt() const
{
    std::cout << "In B's CompBugIt: " << b << " ";
    A::CompBugIt();
}

int
main(int argc, char **argv)
{
    int i;
    B test[10];
    for (i = 0; i < 10; i++) {
	B b(i, 10*i);
	test[i] = b;
    }
    
    for (i = 0; i < 9; i++) {
	test[i].CompBugIt();
	std::cout << std::endl;
    }
    
    B temp[10];
    for (i = 0; i < 10; i++) temp[i] = test[i];

    for (i = 0; i < 10; i++) {
	test[i].~B();
    }
    
    for (i = 9; i >= 0; i--) {
	B b = temp[i];
	test[9-i] = b;
    }
    
    for (i = 0; i < 9; i++) {
	test[i].CompBugIt();
	std::cout << std::endl;
    }
    
    return 0;
}

------------------------- last try with .ii -------------------------------

-- just hung emacs had to kill it. --

-- 
           Summary: Invocation of destructor of element of array changes
                    vtable
           Product: gcc
           Version: 3.4.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: Forest dot Rouse at ansys dot com
                CC: Forest dot Rouse at ansys dot com,gcc-bugs at gcc dot
                    gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22446


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