C ++腐败的堆
我有一个简单的同步队列
template <typename T>
class SynchronisedQueue
{
public:
void Enqueue(const T& data)
{
boost::unique_lock<boost::mutex> lock(queueMutex);
dataQueue.push(data);
conditionVariable.notify_one();
}
T Dequeue()
{
boost::unique_lock<boost::mutex> lock(queueMutex);
while (dataQueue.size()==0)
{
conditionVariable.wait(lock);
}
T result=dataQueue.front(); dataQueue.pop();
return result;
}
private:
std::queue<T> dataQueue; // Use STL queue to store data
boost::mutex queueMutex; // The mutex to synchronise on
boost::condition_variable conditionVariable; // The condition to wait for
};
当我从队列中出队时,我有时会得到堆的腐败....
HEAP:释放后在ccb13c0修改的自由堆块ccb1080
调用堆栈是:
ntdll.dll!76fa5654()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!76f6a554()
ntdll.dll!76f35a70()
ntdll.dll!76fa5eff()
ntdll.dll!76f6a3ba()
ntdll.dll!76f35a70()
msvcr90d.dll!_heap_alloc_base(unsigned int size=1222) Line 105 + 0x28 bytes C
msvcr90d.dll!_heap_alloc_dbg_impl(unsigned int nSize=1186, int nBlockUse=1, const char * szFileName=0x00000000, int nLine=0, int * errno_tmp=0x1310ee18) Line 427 + 0x9 bytes C++
msvcr90d.dll!_nh_malloc_dbg_impl(unsigned int nSize=1186, int nhFlag=0, int nBlockUse=1, const char * szFileName=0x00000000, int nLine=0, int * errno_tmp=0x1310ee18) Line 239 + 0x19 bytes C++
msvcr90d.dll!_nh_malloc_dbg(unsigned int nSize=1186, int nhFlag=0, int nBlockUse=1, const char * szFileName=0x00000000, int nLine=0) Line 296 + 0x1d bytes C++
msvcr90d.dll!malloc(unsigned int nSize=1186) Line 56 + 0x15 bytes C++
msvcr90d.dll!operator new(unsigned int size=1186) Line 59 + 0x9 bytes C++
x.ax!std::_Allocate<unsigned char>(unsigned int _Count=1186, unsigned char * __formal=0x00000000) Line 43 + 0x9 bytes C++
ax.ax!std::allocator<unsigned char>::allocate(unsigned int _Count=1186) Line 145 + 0xb bytes C++
ax.ax!std::vector<unsigned char,std::allocator<unsigned char> >::_Buy(unsigned int _Capacity=1186) Line 1110 + 0xf bytes C++
ax.ax!std::vector<unsigned char,std::allocator<unsigned char> >::vector<unsigned char,std::allocator<unsigned char> >(const std::vector<unsigned char,std::allocator<unsigned char> > & _Right=[1186](83 'S',50 '2',54 '6',67 'C',162 '¢',4 '',0,0,108 'l',0,0,0,2 '',64 '@',0,0,6 '',14 '',64 '@',0,35 '#',2 '',147 '“',76 'L',114 'r',53 '5',0,0,54 '6',79 'O',78 'N',4 '',0,0,0,0,54 '6',79 'O',78 'N',4 '',0,0,0,0,255 'ÿ',255 'ÿ',255 'ÿ',255 'ÿ',255 'ÿ',255 'ÿ',255 'ÿ',255 'ÿ',106 'j',4 '',0,0,0,0,0,1 '',65 'A',154 'š',3 '',1 '',176 '°',159 'Ÿ',255 'ÿ',240 'ğ',199 'Ç',...)) Line 501 + 0x11 bytes C++
ax.ax!SynchronisedQueue<std::vector<unsigned char,std::allocator<unsigned char> > >::Dequeue() Line 32 + 0xc bytes C++
ax.ax!PPin::FillBuffer(IMediaSample * pSample=0x0cadbea8) Line 225 + 0x12 bytes C++
ax.ax!PPin::DoBufferProcessingLoop() Line 300 + 0x13 bytes C++
ax.ax!CSourceStream::ThreadProc() + 0x13e bytes
ax.ax!CAMThread::InitialThreadProc() + 0x51 bytes
kernel32.dll!753bed6c()
ntdll.dll!76f4377b()
ntdll.dll!76f4374e()
什么可能导致这个堆腐败? 如何调试堆损坏错误? 有任何想法吗...
更新:使用示例
// Enqueue
void GetVideoStreams( BYTE *pData)
{
std::vector<BYTE> vecFrame(pData, pData + nLen/sizeof(pData[0]));
IncomingFramesQueue.Enqueue(vecFrame);
}
//Dequeue
void ConsumeVideoStreams()
{
vector<BYTE> data = IncomingFramesQueue.Dequeue();
}
如上所述 - 您的代码和您发布的堆栈跟踪显示正在进行一些内存分配。 再加上错误消息,我认为堆损坏发生在别的地方,每次出队时都会弹出,因为它使用大量内存来复制这些向量。
使用某些内存分析工具的评估版本(例如http://www.softwareverify.com/cpp-memory.php)来查找错误。 市场上还有一些免费工具(最着名的是Valgrind),但我不知道免费的Visual C ++有什么好的工具。
另外,你可以查看这篇文章如何调试堆损坏错误? 这里有关于如何解决这个错误的其他方法。
从我看到的到现在,错误不在您发布的代码中。 如果您需要更多帮助,请提供一个包含错误的小型自包含示例。
我只是找到了一个值得一试的免费工具:Dr. Memory。 当然,我从stackoverflow获得链接。
是,。 很可能您正在混合运行时库的发行版和调试版。
在Windows上(只有AFAIK),有两个不同的运行时库,发布版本会像你期望的那样进行内存分配,但是调试者会在所有分配中添加防护块,以便它可以跟踪缓冲区溢出和其他内存错误。 这个系统的问题是,如果你在同一个应用程序中混合使用Release和Debug库,你将在Release中分配(比如说)10个字节,然后在Debug中释放18个字节(4 + 10 + 4)。
诀窍是每次构建并链接所有Debug或所有发布。 或者,如果您必须在调试版本中使用Release lib,则必须确保在dll中所做的所有分配也由同一个库释放 - 不允许使用CRT新/删除例程,将它们包装在功能。 这可以确保在dll中的10字节的alloc将被相同的dll释放,这显然只会删除10个字节。
编辑:
好的,如果不是这样,那么查看调用堆栈时,如果使用复制构造函数(出列的第32行)分配新的向量时会显示错误,因此首先将该行分割为2个语句,以便您可以查看它的副本,或者导致问题的弹出窗口(我总是倾向于在它们之间放置调试语句,以确保您知道哪一行是问题)。
您的示例代码显示了访问队列的两种不同方式 - > Enqueue和.Dequeue,这表明队列本身更复杂。
这些是非常有用的函数,用于在调试构建中验证堆未损坏:
_ASSERTE(_CrtCheckMemory());
您也可以设置该标志,以便在出口时检查内存泄漏:
通过设置(OR'ing)以下标志:_CRTDBG_LEAK_CHECK_DF
有关更多信息,请参阅以下页面:
http://msdn.microsoft.com/en-us/library/e73x0s4b(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/5at7yxcs.aspx
链接地址: http://www.djcxy.com/p/82307.html