Memory leak in iOS/OS X with String::ToCString

Monkey Forums/Monkey Bug Reports/Memory leak in iOS/OS X with String::ToCString

jjsonick(Posted 2013) [#1]
Part of the Monkey-generated C/Objective-C code is causing a memory leak in iOS and OS X, specifically when a String needs to be converted and the ToCString template is called. This is called everytime a String needs to be converted to an Int, for example.

See this code:

Import mojo

Class MyApp Extends App
	
	Field xpos:Int [256]
	Field ypos:Int [256]
	Field speed:Int [256]
	Field xpos2:Int [256]
	Field ypos2:Int [256]
	Field speed2:Int [256]
	
	Method OnCreate()
	
		SetUpdateRate 30
		
    End
		
	Method OnUpdate()
	
		If TouchDown( 0 )
			ConvertSomeStrings("10,1,1,15,0,62,290")
			ConvertSomeStrings("20,1,0,16,0,92,240")
			ConvertSomeStrings("224,2,0,16,0,32,290")
			ConvertSomeStrings("225,10,0,20,0,22,230")
			ConvertSomeStrings("226,15,0,16,0,12,290")
			ConvertSomeStrings("227,19,0,30,0,92,290")
			ConvertSomeStrings("228,30,0,46,32,32,210")
			ConvertSomeStrings("229,40,0,16,19,92,290")
			ConvertSomeStrings("230,55,0,56,69,92,200")
		Endif
					
	End
	
	Method OnRender()
		Cls
		DrawText "Click or touch screen to do a string to int conversion",0,12
	
	End
		
	Method ConvertSomeStrings(s:String)
					
		Print "String to be converted is " + s
		
		Local p:String [] = s.Split (",")
			
		xpos [ Int (p [0]) ] = Int (p [1])
		ypos [ Int (p [0]) ] = Int (p [2])			
		speed [ Int (p [0]) ] = Int (p [3])
		
		
		xpos2 [ Int (p [0]) ] = Int (p [4])
		ypos2 [ Int (p [0]) ] = Int (p [5])			
		speed2 [ Int (p [0]) ] = Int (p [6])
		
		Print "speed [" + Int (p [0]) + "] is " + speed[Int (p [0])]
		Print "ypos2 [" + Int (p [0]) + "] is " + ypos2[Int (p [0])]
						
	End

End		

Function Main()

	New MyApp
	
End


Using the XCode Memory Leak tracer instrument, in the Allocations view you can see Live Bytes increase with each click or touchscreen touch. And in Leaks view, you see multiple Malloc leaks listed, all pointing to char* String::ToCString<char> in the "Responsible Frame" column -- the red vertical bars in the graph show the times of the clicks/leaks:



Here's that monkey-generated ToCString code:

	template<class C> C *ToCString()const{

		C *p=(C*)malloc( (rep->length+1)*sizeof(C) );	//&Array<C>( rep->length+1 )[0];
		
		for( int i=0;i<rep->length;++i ) p[i]=rep->data[i];
		p[rep->length]=0;
		return p;
	}


From my VERY rudimentary C knowledge, it seems that the array p is being malloced here, and has no corresponding free called on it -- after it has been returned to the calling function, the p pointer has been discarded (since it is local to this template), so the malloced memory can not be referenced to be freed.


SLotman(Posted 2013) [#2]
It shouldn't be released, as far as my knowledge goes. See the return of the function - it's a pointer to a memory area. The area that is created/reserved with malloc.

Have you run the program for a while to see if memory keeps going up forever? GC may kick in sometime and if you're not using that 'malloced' memory area, it should be freed.


jjsonick(Posted 2013) [#3]
The memory does keep going up, increasing as many times as you run the conversion routine. GC does not kick in. If you try the above program, you will see this - the memory added by tapping never gets released. With 5 mins of tapping, I added 7.5 MB to the memory used (live bytes), and that added memory never went down (after leaving it to run for an extra 20 mins with no additional interaction, for example). With a routine looping through strings from a long text file, unreleased/unreleasable memory would grow at a much faster rate.

It seems that the memory not being released is memory used for the *intermediary* step of doing the String to Int conversion. That should be temp memory, and it should be released immediately after the conversion, or at least be eventually GC, but it is not.

This is a problem for bitmap font routines that use conversions from string to ints to do their work, for use of Save/Load String/State that need before or after int conversions, and for frameworks like Ignition that use string to int conversions for some of its loading and object handling routines *and* bitmap fonts.

To see the memory use grow without needing to tap, just comment out the If TouchDown(0) and its corresponding EndIf in Update(). Monitoring an iPad3, that gets me 17.5MB usage at 5 mins, 36 MB at 15 mins, with this relatively modest program.


marksibly(Posted 2013) [#4]
Definitely a leak!