4

I have a simple synchronisedQueue

 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
};

When I Dequeue from queue, I sometimes get corruption of the heap....

HEAP: Free Heap block ccb1080 modified at ccb13c0 after it was freed

call stack is :

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() 

What may cause this heap corruption? How to debug heap corruption errors? Any ideas...

UPDATE: Usage sample

// 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();

}
Novalis
  • 2,265
  • 6
  • 39
  • 63
  • The debug heap is really good at being slow and thus at disguising thread race errors. I suggest you move to the Release mode and just sweep through the program in div-2 manner using HeapValidate(GetProcessHeap(),0,0) to localize the timing issue. I mean validating the heap just before and just after the lines or calls where the errors occur and moving it until it is clear when a heap corruption occurs. Don't forget to use /MD when compiling, though. – ActiveTrayPrntrTagDataStrDrvr Aug 15 '12 at 09:13
  • what is the type of dataQueue? – Tobias Langner Aug 15 '12 at 09:22
  • 4
    You are built in debug mode aren't you? Storage layout of STL varies between the two, so linking non-debug mode against debug mode libraries will go bang! – marko Aug 15 '12 at 09:22
  • data type is : SynchronisedQueue> MyIncomingFramesQueue; so in my case its an vector Tobias – Novalis Aug 15 '12 at 09:25
  • Marko, you mean I should test it in relase mode since it is natural to get this errors in debug mode? – Novalis Aug 15 '12 at 09:26
  • @novalis I mean that you should ensure that your code is built with the same compiler options as the library - specifically with respect to wether it's a debug or release build. – marko Aug 15 '12 at 09:33
  • I don't think it's related, but according to boost's documentation (http://www.boost.org/doc/libs/1_50_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref) the mutex should not be locked when calling notify_one() – Asaf Aug 15 '12 at 09:35
  • @Novalis no, I meant the internal type of your synchronized queue, the dataQueue. You showed me T - but that's not the type of dataQueue or am I mistaken? – Tobias Langner Aug 15 '12 at 10:04
  • @Tobias Langner It is a queue which you caninsert vector type...like this SynchronisedQueue> IncomingFramesQueue; – Novalis Aug 15 '12 at 10:25
  • @Novalis chances are that the heap corruption comes from pop() or front() or push(). But without the sematics & code of the queue it is impossible to answer your question. – Tobias Langner Aug 15 '12 at 11:03
  • @Tobias Langner Well I update the question...put its simple usage code – Novalis Aug 15 '12 at 11:39
  • Note: Your Dequeue function is not exception-safe. – Stephan Dollberg Aug 15 '12 at 11:57
  • it is a single threaded and dataQueue.front(); never called if the que is not empty...But thanksks for quality issue – Novalis Aug 15 '12 at 12:05
  • @Novalis you still don't understand - what's the code of pop(), push(), front(), size(). Or is dataQueue a std::queue? Simply tell us what is the type of dataQueue (it's in the private section of your class SynchronisedQueue. – Tobias Langner Aug 15 '12 at 12:26
  • @Tobias Langner They are standard std::queue dataQueue pop push front...nothing special....I will update that part... – Novalis Aug 15 '12 at 12:30
  • Is the heap corruption always at the same code location or is it a moving target? – Tobias Langner Aug 15 '12 at 12:43
  • it shows same location most of the time...but sometimes very different locations ...but happened after deque.... – Novalis Aug 15 '12 at 12:45
  • dequeue may be misleading. As dequeue allocates a lot of space every time (and is probably called very often), the checking code for the heap canaries is called from there. But the actual overwrite in the heap may have happened everywhere. Since you are copying everything when using your synchronized queue I can't see a memory error in the code you posted. – Tobias Langner Aug 15 '12 at 13:00

3 Answers3

2

As stated above - your code & the stack trace you posted shows that some memory allocation is ongoing. Together with the error message, I assume that the heap corruption happened somewhere else and just pops up every time in dequeue since it uses a lot of memory for copying those vectors.

Use the evaluation version of some memory profiling tool (e.g. http://www.softwareverify.com/cpp-memory.php) to find the error. There are also some free tools on the market (most notably Valgrind) but I don't know any good one for Visual C++ that is for free.

Additionally, you can check this post How to debug heap corruption errors? here for additional methods on how to tackle this error.

From what I've seen until now, the error's not in the code you posted. If you want more help, provide a small self contained example with the error.


I just found a free tool that might be worth a try: Dr. Memory. I got the link from stackoverflow of course.

Community
  • 1
  • 1
Tobias Langner
  • 10,634
  • 6
  • 46
  • 76
1

Yes,. chances are you're mixing the Release and Debug versions of the runtime library.

On Windows (only AFAIK) there are 2 different runtime libraries, the release version does memory allocs as you'd expect, but the debug one adds guard blocks around all allocations so it can track buffer overflows and other memory errors. The problem with this system is that if you mix a Release and a Debug library in the same application, you will allocate (say) 10 bytes in Release and then free 18 bytes (4+10+4) in Debug.

The trick is to build and link either all Debug or all Release, every time. Alternatively, if you must use a Release lib in a debug build, then you must ensure that all allocations made in a dll is also freed by that same library - do not allow the CRT new/delete routines to be used, wrap them in a function. this ensures that the 10 byte alloc in dll A will be freed by the same dll, which obviously will only delete the 10 bytes.

EDIT:

ok, if it's not that, then looking at the call stack shows the error when allocating a new vector using the copy constructor (line 32 of Dequeue), so firstly split that line into 2 statements so you can see if its the copy, or the pop that's causing the problem (I always tend to put a debug statement between them just to make really sure you know which line is the problem).

Your sample code shows 2 different ways of accessing the queue ->Enqueue and .Dequeue which suggests more complexity in the queue itself.

gbjbaanb
  • 51,617
  • 12
  • 104
  • 148
0

These are extremely helpful functions to call to verify that the heap is not corrupted in debug build:

_ASSERTE( _CrtCheckMemory( ) );

You can also set the flag so that you check for memory leaks on exit:

By setting (OR'ing) the following flag: _CRTDBG_LEAK_CHECK_DF

See the following pages for more info:

http://msdn.microsoft.com/en-us/library/e73x0s4b(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/5at7yxcs.aspx

kashiraja
  • 740
  • 11
  • 24