【问题标题】:Multiple Memory Leaks - Vector and Pointer多个内存泄漏 - 向量和指针
【发布时间】:2016-07-20 10:47:57
【问题描述】:

我的应用程序一直存在内存泄漏问题,并且由于它位于物理模块中(几乎所有东西都使用它),因此导致应用程序运行缓慢。通过使用 Visual Leak Detector,我发现大多数泄漏是由于构造函数和 ApplyGravity 函数而发生的。

ParticleModel::ParticleModel(Transform* transform)
{
 _transform = transform;
 Acceleration = XMFLOAT3(0.0f, 0.0f, -0.1f);
 mass = 10.0f;
 force = XMFLOAT3(0.0f, 0.0f, 0.0f);
 velocity = XMFLOAT3(0.0f, 0.0f, 0.0f);
 netForce = XMFLOAT3(0.0f, 0.0f, 0.0f);
 forceMag = 0.0f;
 sForce = XMFLOAT3(0.0f, 0.0f, 0.0f);
 dragFactor = 1.0f;
 gravity = -9.81f;

 _usingGravity = false;
 _useConstAcc = true;
 laminar = true;

 radius = 0.5f;

 CollisionCheck = false;

 boolsForce = true;

 move.x = 0.0f;
 move.y = 0.0f;
 move.z = 0.0f;
 moveBy = 0.0f;
}

我注释掉了除了 _transform = transform; 之外的所有变量。并且构造函数的内存泄漏仍然发生,另外我要注意的是,我正在释放类的析构函数中指针的内存,尽管我不确定这是否是最好的地方。

ParticleModel::~ParticleModel()
{
    delete _transform;
}

ApplyGravity 中的第二次内存泄漏:

void ParticleModel::ApplyGravity()
{
  _temp = XMFLOAT3(0.0f, gravity, 0.0f);
  _forces.push_back(_temp); //_forces is a vector of XMFLOAT3s 
}

我玩过清除矢量,但无济于事,因为泄漏仍然发生。

输出:

Leak Hash: 0x5522F309, Count: 1, Total 12 bytes
  Call Stack (TID 1556):
   MSVCR120D.dll!operator new()
c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0 (848): DX11 Framework.exe!std::_Wrap_alloc<std::allocator<DirectX::XMFLOAT3> >::allocate()
c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector (1588): DX11 Framework.exe!std::vector<DirectX::XMFLOAT3,std::allocator<DirectX::XMFLOAT3> >::_Reallocate() + 0x17 bytes
c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector (1619): DX11 Framework.exe!std::vector<DirectX::XMFLOAT3,std::allocator<DirectX::XMFLOAT3> >::_Reserve()
c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector (1258): DX11 Framework.exe!std::vector<DirectX::XMFLOAT3,std::allocator<DirectX::XMFLOAT3> >::push_back()
 particlemodel.cpp (58): DX11 Framework.exe!ParticleModel::ApplyGravity()
particlemodel.cpp (290): DX11 Framework.exe!ParticleModel::Update()
gameobject.cpp (27): DX11 Framework.exe!GameObject::Update() + 0x1F bytes
 bbparticle.cpp (193): DX11 Framework.exe!BBParticle::Update()
smokeemitter.cpp (54): DX11 Framework.exe!SmokeEmitter::Update()
 application.cpp (1254): DX11 Framework.exe!Application::Update() + 0x30 bytes
main.cpp (67): DX11 Framework.exe!wWinMain()
 f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (466): DX11   Framework.exe!wWinMainCRTStartup()
 KERNEL32.DLL!BaseThreadInitThunk() + 0x24 bytes
 ntdll.dll!RtlUnicodeStringToInteger() + 0x253 bytes
 ntdll.dll!RtlUnicodeStringToInteger() + 0x21E bytes
    Data:
     00 00 00 00    C3 F5 1C 41    00 00 00 00                    .......A ........

我认为发生的所有其他泄漏都是由于在输出中列出的所有位置调用了 ParticleModel。例如 ParticleModel::Update() 调用 ApplyGravity 等等。

【问题讨论】:

  • 您是动态创建ParticleModel 吗?每个new 都有一个delete 吗?
  • ParticleModel 的用户定义复制构造函数和赋值运算符在哪里?

标签: c++ debugging directx


【解决方案1】:

你说你在析构函数中删除了指针:

ParticleModel::~ParticleModel()
{
    delete _transform;
}

然而,构造函数并不是这个对象被分配的地方。它被传递到构造函数中,并设置为类成员。内存泄漏的一个可能原因是在代码路径中分配了该对象的新实例,但没有存储在任何地方,或者传递给ParticleModel 的新实例,因此永远不会被破坏。

这违反了RAII model。

另外,这个类可能是violates the Rule Of Three,这可能是另一个内存泄漏源。即使这个动态范围的对象总是被传递给构造函数,如果没有正确遵循三规则,内存泄漏仍然可能发生;与可能的内存损坏配对,作为额外的奖励。

构造函数中似乎没有其他任何东西可以分配任何内存,并且可能会泄漏任何东西。试图定位内存泄漏源的工具并不总是可靠的,而且它们的输出有时难以理解。

遵循公认的设计原则,正确地设计你的课程总是更好的,而不是在风雨飘摇的地方全速前进,并依靠调试工具来发现和修复任何导致的问题。

为了能够验证不可能有任何内存泄漏,RAII 原则规定动态范围的对象或任何类型的资源必须在构造函数中分配,并在析构函数(赋值运算符正确处理该过程,以遵守三规则)。如果您无法追踪内存泄漏的实际来源,那么通过正确地重新设计您的类,您最终可能会修复潜在的错误。

【讨论】:

    【解决方案2】:

    如果是指针向量,您必须显式删除。看看这个帖子,它可能对你有帮助.. Does vector::erase() on a vector of object pointers destroy the object itself?

    同样在 ParticleModel 中,您注释掉了构造函数并尝试删除 _transform ... 错误会达到目的吗? :) .. 我想问题出在构造函数调用上,请发布详细代码..

    【讨论】:

      猜你喜欢
      • 2019-04-18
      • 1970-01-01
      • 2012-11-15
      • 1970-01-01
      • 2013-10-31
      • 2015-12-15
      • 2012-09-08
      • 1970-01-01
      • 2013-04-06
      相关资源
      最近更新 更多