非法内存访问错误

时间:2013-11-06 23:30:37

标签: c++ memory memory-management unique-ptr

我有一个错误,似乎导致访问已经被清除的内存。 有两个类--B类(包含C类的结构实例和D类的unique_ptrs)和A类,它包含B类对象的向量。 以下是导致错误的区域的代码结构:

void foo{
  A localA(...);
  bar(&localA);
  baz(localA);
}

void bar(A* a) {
  C c1 = constructLocalC1();
  D d1 = constructLocalD1();
  a.insertB(c1, &d1);
}

请注意,insertB将调用类B的构造函数 - 类似于:

void A::insertB(C c, D* d) {
  bVector.push_back(B(c, d));
}

B::B(C cIn, D* dIn) : c_(cIn) { d_ = make_unique<D>(*dIn); }  

B {
public:
  B(C c, D* d);
  C c_;
  std::unique_ptr<D> d_;
}

constructLocalC1()的实现看起来像(类似于constructLocalD1()

 C constructLocalC1() {
   C c1;
   c1.blah = computeBlahParameter(); // blah is of type int
   c1.bleh = computeBlehParameter(); // bleh is of type double
   return c1;
}

观察结果是当baz尝试访问localA中存在的c1(副本)时,其中的值已损坏且与bar设置的值不同。根据这一观察结果,我得出的结论是存储B的向量存储了一个已经解除分配的元素。

我知道通过这里的代码片段了解根本原因有点复杂,因为这是非常抽象的 - 很高兴提供所需的更具体的细节。

此代码段中有哪些潜在的陷阱和内存泄漏原因?什么是接近调试的好方法?

1 个答案:

答案 0 :(得分:0)

您的问题可能是您没有在bar内的对象上动态分配内存。 如果在函数中创建一个非显式或隐式动态分配的对象(使用new,或者使用临时对象),那么您的对象就会在堆栈上创建,并且会立即销毁它们。它们超出范围(在您的情况下,函数返回时)。一个选项是为插入到向量中的对象分配内存,但在内存处理和释放时要非常小心,好像处理不当会导致内存泄漏。你也可以使用智能指针(Boost库有一个很好的实现,但也添加在STL),这将通过RAII概念方法防止这种情况(有关RAII的更多信息,请看这个话题:RAII and smart pointers in C++)。