FileOutputStream leak JUCE Assertion failure


#1

Hi, I use this code, for download and save file

 Result jsonDownload::download(const URL remoteFile, const File localfile)
 {
StringPairArray responseHeader;
int statusCode = 302;

ScopedPointer<InputStream> in =
	remoteFile.createInputStream(false, nullptr, nullptr, String(), 10000, &responseHeader, &statusCode, 0);

if (in == nullptr || statusCode != 200)
{
	signalThreadShouldExit();
	return Result::fail("server reply error code:" + String(statusCode));
}

MemoryBlock mb;
MemoryOutputStream mo(mb, false);
ScopedPointer<FileOutputStream> fo = localfile.createOutputStream();

int64 size = in->getTotalLength();
int64 bytesReceived = -1;
for (int64 pos = 0; pos < size; pos += bytesReceived)
{
	if (threadShouldExit())
		return Result::fail("Download error: operation interrupted");
	bytesReceived = mo.writeFromInputStream(*in, 8192);
	if (bytesReceived == 0)
		return Result::fail("Download error: lost connection");
	fo->write(mo.getData(), mo.getDataSize());
	mo.reset();
	updateLabelText(localfile.getFileNameWithoutExtension() + " " + String( ceil(((double)pos / (double)size)*100)) + " pos:"+String(pos));
	//fo.flush();
}
return Result::ok();
}

it’s work fine, but in debug I see leak protect message.

0x014c1164 {test.exe!juce::LeakedObjectDetectorjuce::FileOutputStream::LeakCounter counter} {…} juce::LeakedObjectDetectorjuce::FileOutputStream::LeakCounter *
*** Leaked objects detected: 1 instance(s) of class FileOutputStream
JUCE Assertion failure in juce_leakedobjectdetector.h:88

before that, i used FileOutputStream without scopepointer just FileOutputStream fo = localfile and sometimes app crashed. how fix that error message? maybe this not best way download files?


#2

Eventually I’m using this code. I still get a leak message. But it works fine. Maybe this will help someone

Result jsonDownload::download(const URL remoteFile, const File localfile)
{
StringPairArray responseHeader;
int statusCode = 302;
ScopedPointer<InputStream> in =	remoteFile.createInputStream(false, nullptr, nullptr, String(), 10000, &responseHeader, &statusCode, 0);

if (in == nullptr || statusCode != 200)
{
	signalThreadShouldExit();
	return Result::fail("server reply error code:" + String(statusCode));
}
FileOutputStream fo = localfile;
int64 size = in->getTotalLength();
int64 bytesReceived = 0;

int64 bytesToWrite = -1;
if (size > 1000000)
	bytesToWrite = size / 100;
else if (size > 10000000)
	bytesToWrite = size / 1000;
else if (size > 100000000)
	bytesToWrite = size / 10000;
else bytesToWrite = -1;

int64 pos = 0;
while(pos < size)
{
	if (threadShouldExit())
		return Result::fail("Download error: operation interrupted");
	bytesReceived = fo.writeFromInputStream(*in, bytesToWrite);
	if (bytesReceived == 0)
		return Result::fail("Download error: lost connection");
	updateLabelText(localfile.getFileNameWithoutExtension() + " " + String( ceil(((float)pos / (float)size)*100)));
	pos += bytesReceived;
}
return Result::ok();
 }

#3

I can’t spot what’s going wrong there.

When you you hit the leak detector assertion failure if you “continue” in the debugger it will probably tell you about other objects being leaked. Often this will reveal the real cause of the problem.


#4

Yes, odd… can’t see any way for that file stream to leak.

It’s not something silly like this happens on a thread that’s still running when your app is shutting down?


#5

Right, and make sure, you add either
JUCE_LEAK_DETECTOR (jsonDownload) or
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (jsonDownload) in your class definition, to catch leaks of that class as well (usually the reason, why members of that class are found leaking).


#6

Yes, the problem was in other object. Thank you