Heap Corruption in URL::createInputStream (Multithreaded)


#1

Hi,

I'm creating an application that communicates with a website using HTTP Post Requests. It is multithreaded and sends many requests in short periods. After a while, no matter how many threads are sending requests, I get an error like this:

HEAP[Application.exe]: HEAP: Free Heap block 63815d8 modified at 6381600 after it was freed

This happens to debug and release on any version of windows and also on mac. I've searched and found some similar topics but nothing that would give me a solution.

Below is one of the call stacks from VS2013. Thanks in advance for any help.

     ntdll.dll!_RtlpBreakPointHeap@4()    Unknown
     ntdll.dll!@RtlpAllocateHeap@24()    Unknown
     ntdll.dll!_RtlAllocateHeap@12()    Unknown
     ntdll.dll!_RtlDebugAllocateHeap@12()    Unknown
     ntdll.dll!@RtlpAllocateHeap@24()    Unknown
     ntdll.dll!_RtlAllocateHeap@12()    Unknown
     wininet.dll!DirectAccessResolver::GetProxyForUrl()    Unknown
     wininet.dll!WininetProxyManager::OnProcessGetProxyForUrl()    Unknown
     wininet.dll!WininetProxyManager::GetProxyForUrl()    Unknown
     wininet.dll!InternalInternetGetProxyForUrl()    Unknown
     wininet.dll!HTTP_REQUEST_HANDLE_OBJECT::HttpSendRequest_WindowsGetProxyForUrl()    Unknown
     wininet.dll!HTTP_REQUEST_HANDLE_OBJECT::HttpSendRequest_Start()    Unknown
     wininet.dll!CFsm_HttpSendRequest::RunSM()    Unknown
     wininet.dll!CFsm::Run()    Unknown
     wininet.dll!DoFsm()    Unknown
     wininet.dll!HttpWrapSendRequest()    Unknown
     wininet.dll!HttpSendRequestExW()    Unknown
>    Application.exe!juce::WebInputStream::openHTTPConnection(URL_COMPONENTSW & uc, bool (void *, int, int) * progressCallback, void * progressCallbackContext) Line 279    C++
     Application.exe!juce::WebInputStream::openConnection(URL_COMPONENTSW & uc, void * sessionHandle, bool (void *, int, int) * progressCallback, void * progressCallbackContext) Line 250    C++
     Application.exe!juce::WebInputStream::createConnection(bool (void *, int, int) * progressCallback, void * progressCallbackContext) Line 214    C++
     Application.exe!juce::WebInputStream::WebInputStream(const juce::String & address_, bool isPost_, const juce::MemoryBlock & postData_, bool (void *, int, int) * progressCallback, void * progressCallbackContext, const juce::String & headers_, int timeOutMs_, juce::StringPairArray * responseHeaders) Line 50    C++
     Application.exe!juce::URL::createInputStream(bool usePostCommand, bool (void *, int, int) * progressCallback, void * progressCallbackContext, juce::String headers, int timeOutMs, juce::StringPairArray * responseHeaders, int * statusCode) Line 350    C++
     Application.exe!Communicator::run() Line 151    C++
     Application.exe!juce::Thread::threadEntryPoint() Line 106    C++
     Application.exe!juce::juce_threadEntryPoint(void * userData) Line 114    C++
     Application.exe!juce::threadEntryProc(void * userData) Line 103    C++
     [External Code]    

 


#2

It generally means that you're deleting a dangling pointer somewhere. If it happens the same on all platforms, it's almost certainly a bug in your code rather than the juce URL functionality itself, which is implemented completely differently on each OS.


#3

Thanks Jules. I asked here because I'm only using ScopedPointers and it doesn't happen to every request sent, but to one of them after some random period. Anyway, I'll review my code to see what I'm doing wrong and make more tests.

Thank you.


#4

I still haven't solved this issue. I've removed the http request part to see if it would be stable but it keeps crashing in different String assignments. Like this one, for example, which is very simple:

sessionObj->setStatus(status + runningProfiles);

[...]

void Communicator::setStatus (String message)
{
    statusMessage = message;
}

I have many instances of a component and this is called from different threads at random times constantly. It also crashes on StringPairArray assignments.

Is it possible that String assignment is not thread safe in my code? If so how can I make sure it won't crash?

My case looks similar to the one discribed in this 4 years old thread: http://www.juce.com/forum/topic/string-assignment-not-threadsafe

Here's the callstack from the crash in the code above.

     ntdll.dll!_RtlpBreakPointHeap@4()    Unknown
     ntdll.dll!@RtlpAllocateHeap@24()    Unknown
     ntdll.dll!_RtlAllocateHeap@12()    Unknown
     ntdll.dll!_RtlDebugAllocateHeap@12()    Unknown
     ntdll.dll!@RtlpAllocateHeap@24()    Unknown
     ntdll.dll!_RtlAllocateHeap@12()    Unknown
     Application.exe!_heap_alloc_base(unsigned int size) Line 58    C
     Application.exe!_heap_alloc_dbg_impl(unsigned int nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 431    C++
     Application.exe!_nh_malloc_dbg_impl(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 239    C++
     Application.exe!_nh_malloc_dbg(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine) Line 302    C++
     Application.exe!malloc(unsigned int nSize) Line 56    C++
     Application.exe!operator new(unsigned int size) Line 59    C++
     Application.exe!operator new[](unsigned int count) Line 6    C++
     Application.exe!juce::StringHolder::createUninitialisedBytes(unsigned int numBytes) Line 77    C++
     Application.exe!juce::StringHolder::makeUniqueWithByteSize(const juce::CharPointer_UTF8 text, unsigned int numBytes) Line 198    C++
     Application.exe!juce::String::preallocateBytes(unsigned int numBytesNeeded) Line 297    C++
     Application.exe!juce::String::appendCharPointer(const juce::CharPointer_UTF8 startOfTextToAppend, const juce::CharPointer_UTF8 endOfTextToAppend) Line 651    C++
     Application.exe!juce::String::appendCharPointer(const juce::CharPointer_UTF8 textToAppend) Line 635    C++
     Application.exe!juce::String::operator+=(const juce::String & other) Line 675    C++
     Application.exe!juce::operator+(juce::String s1, const juce::String & s2) Line 734    C++
>    Application.exe!MainSubComponent::run() Line 736    C++
     Application.exe!juce::Thread::threadEntryPoint() Line 106    C++
     Application.exe!juce::juce_threadEntryPoint(void * userData) Line 114    C++
     Application.exe!juce::threadEntryProc(void * userData) Line 103    C++
     [External Code]