【发布时间】:2014-01-23 19:37:48
【问题描述】:
我有以下问题。我循环运行了 3000 次。每次通过时,我都会在堆上分配一个字节缓冲区:
uint8_t* frameDest;
try {
frameDest= new uint8_t[numBytes * sizeof(uint8_t)];
memcpy(frameDest, frameSource, _numBytes);
} catch(std::exception &e) {
printf(e.what());
}
因此,分配的帧用作来自某些 frameSource._numBytes 的数据的目的地,它等于 921600。
接下来,在同一个循环中,frameDest 被推入 uint8_t* 指针(_frames_cache)的 std::vector。这个向量用作帧缓存并在每 X 帧被清理一次。使用当前设置,当超过 20 个时清理向量帧在缓存中。清理缓存的方法是这样的:
void FreeCache()
{
_frameCacheMutex.lock();
try {
int cacheSize = _frames_cache.size();
for (int i = 0; i < cacheSize; ++i) {
uint8_t* frm = _frames_cache.front();
_frames_cache.erase(_frames_cache.begin());
delete [] frm;
}
} catch (std::exception& e) {
printf(e.what());
}
_frameCacheMutex.unlock();
}
问题:在第一个代码块中约 2000+ 帧之后引发了错误的分配异常。我用 Dr.Memory 测试了内存泄漏,但没有发现。此外,我在其他部分的分配/解除分配上没有收到错误或异常的程序。我有 2 个这样的代码实例在 2 个单独的线程中运行,这意味着在该程序的整个生命周期中,大约 6000 个分配/释放被处理,每个 960000 个字节。在整个应用程序中,有更多的堆分配,但是不是本部分中的频率。我已经读到现代编译器以非常先进的方式处理堆管理,但我仍然怀疑我的问题与内存碎片有关。我使用 Visual C++ 2012 编译器(C++ 11),32 位Windows7 64位操作系统下。
我的问题是:内存管理问题的可能性有多大,我应该编写还是使用自定义堆分配管理器?如果不是,会是什么?
【问题讨论】:
-
“目前超过...”你能改写一下吗?
-
2000x~1M大约是2G。切换到 64 位。
-
frameDest= new uint8_t[numBytes * sizeof(uint8_t)];这是错误的:你永远不需要* sizeof和new。只需写frameDest = new uint8_t[numBytes];(当然,sizeof(uint8_t)无论如何都应该是 1!) -
如果您在 2G/2G 分离的 32 位系统上保持在 2G 附近(Win32 AFAIK 的默认设置),您将始终面临随机分配失败的风险。如果你想保持 32 位,你需要非常非常小心地管理你的缓存(在启动时分配固定大小可能是最明智的做法)
-
@dyp Boost Pointer Container 值得一看
标签: c++ visual-c++ memory-management