String createInternal failing


#1

Jules, I’m using a filelogger, and running into problems when the log gets too big. This:

[code]void String::createInternal (const int numChars) throw()
{
jassert (numChars > 0);

text = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder)
                                                       + numChars * sizeof (tchar));
text->refCount = 1;
text->allocatedNumChars = numChars;
text->text[0] = 0;

}
[/code]

Throws an exception when text comes out NULL, with a file size of 1040012127. It’s less than an int, but it gets multiplied by a tchar - how big is that? If it’s bigger than 3, we’re busting the int barrier, so that may be it. Seems unlikely it’s memory.

Not that it matters, but this is all in the file-logger opening the log to truncate it.

As a stop gap, I’m trying something like:

[code] int allocChars = numChars;

if (sizeof (InternalRefCountedStringHolder) + (allocChars * sizeof (tchar)) > sizeof(int))
	allocChars	= (sizeof(int) - sizeof (InternalRefCountedStringHolder)) / sizeof (tchar);
	
text = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder)
                                                       + allocChars * sizeof (tchar));

	text = (InternalRefCountedStringHolder*) juce_malloc (sizeof(int));

text->refCount = 1;
text->allocatedNumChars = allocChars;

[/code]

I’d guess you have a better fix in a more appropriate place?

Bruce


#2

That’s interesting… the file logger shouldn’t really be loading and unloading such a massive file as a string - that could end up being gigabytes.

Try this as a better implementation of the trimming function in the FileLogger class. (You’ll also need to add an include for FileInputStream.h)

[code]
void FileLogger::trimFileSize (int maxFileSizeBytes) const
{
if (maxFileSizeBytes <= 0)
{
logFile.deleteFile();
}
else
{
const int64 fileSize = logFile.getSize();

    if (fileSize > maxFileSizeBytes)
    {
        FileInputStream* const in = logFile.createInputStream();
        jassert (in != 0);

        if (in != 0)
        {
            in->setPosition (fileSize - maxFileSizeBytes);
            String content;

            {
                MemoryBlock contentToSave;
                contentToSave.setSize (maxFileSizeBytes + 4);
                contentToSave.fillWith (0);

                in->read (contentToSave.getData(), maxFileSizeBytes);
                delete in;

                content = contentToSave.toString();
            }

            int newStart = 0;

            while (newStart < fileSize
                    && content[newStart] != '\n'
                    && content[newStart] != '\r')
                ++newStart;

            logFile.deleteFile();
            logFile.appendText (content.substring (newStart), false, false);
        }
    }
}

}[/code]


#3

Huh. This has worked fine for a while, but now I’m profiling and debugging, and the log gets big. The end result is that I’m spending 20% of the app’s time in trimFileSize() (in FileInputStream::read())

Is there a ‘fix’ for that? Do I need to do multiple log files? Can we just trim a lot more so that we don’t hit limits so often?

Bruce


#4

Can’t think of a faster way of doing it - if it’s a problem, I guess you’d just need to turn off trimming and let the file keep growing…


#5