I’ve got a crash I don’t understand. Can someone check I’m not doing anything stupid? It looks like, though doesn’t explicitly say in the documentation that (1) the MemoryBlock will be automatically resized and (2) allocation errors will throw or assert.
The crash is happening on readIntoMemoryBlock() where I get a write access error when the downloaded file exceeds a few Mb in size.
ServerOutcome LoopCloudApi::downloadCloudData(const String& downloadLink, const File& destination, URL::OpenStreamProgressCallback * callback, void * callbackContext)
{
auto url = URL(downloadLink);
int statusCode{ 0 };
ScopedPointer<InputStream> in = url.createInputStream(false, callback, callbackContext, String(), 0, nullptr, &statusCode);
if (in != nullptr && statusCode == 200)
{
MemoryBlock memory;
auto bytesReceived = 0;
for (;;)
{
auto b = in->readIntoMemoryBlock(memory, 63556);
bytesReceived += int(b);
if (callback)
{
auto shouldContinue = callback(callbackContext, bytesReceived, -1);
if (!shouldContinue)
return ServerOutcome::connectionError; // actually aborted by use
}
if (b == 0)
break;
}
Very odd - looks fine to me, and we use MemoryInputStreams in hundreds of places to load much larger blocks than a few MB… Let us know if you find out any more clues.
I thought it was a threading issue to start with - it’s on a second thread. But the thread isn’t being killed, and I’m assuming the functions I’m calling are okay to call outside the message thread.
So I’m just retrying a few times - see if it stops after exactly the same number of bytes each time…
@jules … okay - so it cannot allocate the memory (for some reason yet to be determined - we are only using 800Mb overall for the applicaiton) so realloc returns nullptr. However it doesn’t throw - because the HeapBlock in MemoryBlock is set to not throw.
And then your check in MemoryOutputStream::write is duff:
if (char* dest = prepareToWrite (howMany))
{
memcpy (dest, buffer, howMany);
return true;
}
Because prepareToWrite adds the size onto a null ptr and therefore doesn’t return null as an error code.
Ah, well yes… when you said “a few MB” I didn’t think you mean 800, that’s the kind of size where the OS could easily fail to allocate a contiguous block of that size.
I think it looked like you could return a nullptr somewhere and everything would be fine as well … anything better than what it does right now though - i’d settle for an exception but it’s not really the JUCE way
Anyway - I’d guess I’d better avoid doing what I’m doing for larger files…