C++ 将对象插入向量时出现内存错误

C++ 将对象插入向量时出现内存错误,c++,segmentation-fault,memory-corruption,C++,Segmentation Fault,Memory Corruption,我写了一个简单的类: class A { private: // a bunch of attributes int *a; public: A() { cout << "constructor called" << endl; } ~A() { cout << "destructor called" << endl; if (a) delete[

我写了一个简单的类:

class A
{
  private:
    // a bunch of attributes
    int *a;
  public:
    A()  { 
        cout << "constructor called" << endl;
    }
    ~A() { 
        cout << "destructor called" << endl;
        if (a) delete[] a;
    }
    void initialize(int i) {
        //does the initialization
        a = new int[i];
    }
};
事实上,当我运行这个程序时,我期望得到10个消息
构造函数调用
,然后得到10个消息
析构函数调用
,但我得到的是以下输出:

constructor called
destructor called
constructor called
destructor called
destructor called
constructor called
destructor called
*** glibc detected *** ./test.o: double free or corruption (fasttop): 0x00000000022bc030 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f823cd49b96]
./test.o[0x400d3b]
./test.o[0x401924]
./test.o[0x401672]
./test.o[0x401107]
./test.o[0x400fb5]
./test.o[0x4014d5]
./test.o[0x401012]
./test.o[0x400e79]
./test.o[0x400bd1]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f823ccec76d]
./test.o[0x400ac9]
======= Memory map: ========
00400000-00403000 r-xp 00000000 00:20 286720734                          /home/users/u5410055/Desktop/test.o
00602000-00603000 r--p 00002000 00:20 286720734                          /home/users/u5410055/Desktop/test.o
00603000-00604000 rw-p 00003000 00:20 286720734                          /home/users/u5410055/Desktop/test.o
022bc000-022dd000 rw-p 00000000 00:00 0                                  [heap]
7f823c9cf000-7f823caca000 r-xp 00000000 08:03 721005                     /lib/x86_64-linux-gnu/libm-2.15.so
7f823caca000-7f823ccc9000 ---p 000fb000 08:03 721005                     /lib/x86_64-linux-gnu/libm-2.15.so
7f823ccc9000-7f823ccca000 r--p 000fa000 08:03 721005                     /lib/x86_64-linux-gnu/libm-2.15.so
7f823ccca000-7f823cccb000 rw-p 000fb000 08:03 721005                     /lib/x86_64-linux-gnu/libm-2.15.so
7f823cccb000-7f823ce80000 r-xp 00000000 08:03 720994                     /lib/x86_64-linux-gnu/libc-2.15.so
7f823ce80000-7f823d080000 ---p 001b5000 08:03 720994                     /lib/x86_64-linux-gnu/libc-2.15.so
7f823d080000-7f823d084000 r--p 001b5000 08:03 720994                     /lib/x86_64-linux-gnu/libc-2.15.so
7f823d084000-7f823d086000 rw-p 001b9000 08:03 720994                     /lib/x86_64-linux-gnu/libc-2.15.so
7f823d086000-7f823d08b000 rw-p 00000000 00:00 0 
7f823d08b000-7f823d0a0000 r-xp 00000000 08:03 30391                      /lib/x86_64-linux-gnu/libgcc_s.so.1
7f823d0a0000-7f823d29f000 ---p 00015000 08:03 30391                      /lib/x86_64-linux-gnu/libgcc_s.so.1
7f823d29f000-7f823d2a0000 r--p 00014000 08:03 30391                      /lib/x86_64-linux-gnu/libgcc_s.so.1
7f823d2a0000-7f823d2a1000 rw-p 00015000 08:03 30391                      /lib/x86_64-linux-gnu/libgcc_s.so.1
7f823d2a1000-7f823d383000 r-xp 00000000 08:03 390571                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7f823d383000-7f823d582000 ---p 000e2000 08:03 390571                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7f823d582000-7f823d58a000 r--p 000e1000 08:03 390571                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7f823d58a000-7f823d58c000 rw-p 000e9000 08:03 390571                     /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7f823d58c000-7f823d5a1000 rw-p 00000000 00:00 0 
7f823d5a1000-7f823d5c3000 r-xp 00000000 08:03 721006                     /lib/x86_64-linux-gnu/ld-2.15.so
7f823d796000-7f823d79b000 rw-p 00000000 00:00 0 
7f823d7bf000-7f823d7c3000 rw-p 00000000 00:00 0 
7f823d7c3000-7f823d7c4000 r--p 00022000 08:03 721006                     /lib/x86_64-linux-gnu/ld-2.15.so
7f823d7c4000-7f823d7c6000 rw-p 00023000 08:03 721006                     /lib/x86_64-linux-gnu/ld-2.15.so
7fff1f4c4000-7fff1f4e5000 rw-p 00000000 00:00 0                          [stack]
7fff1f564000-7fff1f565000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted (core dumped)

语法错了吗?在代码中应该考虑什么变化?

< p>向量中的10个对象的10个指针*A都指向同一个地址,所以你得到了双自由

< p>这并不意味着你创建向量的方式看起来是个好主意,但是我注意到了眼前的问题,是指您不初始化类a的
a
成员。
一旦调用了dtor,这个/will/blow就会发生,除非之前调用了initialize()。

您的问题与
vector
完全无关。我可以复制您的问题,而无需使用
vector

在进一步学习之前,请尝试让您的课程学习以下课程:

int main()
{
   A a1;
   a1.initialize(1);
   A a2 = a1;
   A a3;
   a3 = a1;
}

此程序必须无错误地完成,没有内存泄漏,不崩溃,没有双删除等。一旦你得到了与你的类一起工作的小程序,然后你才可以把它放在一个容器中,比如<代码> vector < /代码>。 上面的程序进行构造、复制/分配和销毁,

vector
将/可能对放置在其中的对象执行的所有操作


上述程序的一个变体是删除对
a1的调用。初始化
并查看发生了什么(这将测试仅构造默认值时发生的情况)

想想如果在代码中的某个地方执行
{A;}
会发生什么。析构函数会做什么?顺便说一句,
delete nullptr
是完全安全的。您在这里拥有的不是。@fstd如何确保分配了?
if(a)
if(a!=NULL
没有work@emab[a指向的内存]是在您分配后分配的:)。在此之前,除非进行了初始化(您没有进行初始化),否则a将保存一个垃圾指针。最后,您对垃圾使用delete[],这似乎不正确。你是如何得出这个结论的?当我尝试创建一个对象时,我发现分割错误;那么,这有什么解释?@enab-该成员指针
a
未初始化。然后在析构函数中执行以下操作:
if(a)delete[]aa
未初始化,因此它指向垃圾。因此,您正在垃圾指针上调用
delete
。很抱歉,我没有看到main()。我以为这10个对象刚才是被容器复制的。嗯,我想知道为什么我对这个答案的每一条评论都得到-1个代表(这甚至不是我的)。我想
向量
把事情搞砸了;它首先创建一个对象,将该对象复制到向量中,然后销毁它(未初始化)。这是正确的吗?通过提供复制构造函数和复制赋值操作符,您有责任确保您的对象是可复制的。向量只调用这些函数(如果不定义它们,则会得到编译器生成的版本,这对于类来说是错误的)。如果要禁用这些函数,请将它们设置为私有(或C++11中的
=delete;
),当您尝试将对象放入向量时,将出现编译错误。您的解释是正确的,可以理解的;但我需要将对象推入
向量
,然后初始化这些值;否则,vector将使用大量时间和内存执行两次(一次用于创建此对象,另一次用于将其复制到vector中);你认为我应该使用数组而不是向量吗?为什么不让默认构造函数使用可选参数呢<代码>A(intx=0):A(0){if(x>0)初始化(x);}
std::vector A(10,4)
将初始化值为4的所有条目。此外,使用阵列也不会获得任何进一步的好处。无论如何,如何从数组中删除项?数组的大小是固定的。
使用了大量的时间和内存
我已经听过很多次了,几乎在所有情况下,这些警报都不是问题,或者完全是错误的。我没有使用构造函数的原因就是我解释的。假设
i
的值非常大(比如$10^8$),每次初始化都需要几秒钟;如果我把它放在构造函数中,vector将使运行时间加倍(因为它构造了这个对象的两个副本)。许多人执行一个
placement new
调用来分配整个内存池,然后用对象“填充”内存池。因此,只创建一组对象。
int main()
{
   A a1;
   a1.initialize(1);
   A a2 = a1;
   A a3;
   a3 = a1;
}