Is this a mem leak?
BlitzMax Forums/BlitzMax Beginners Area/Is this a mem leak?
Okay, is the following a mem leak?
Socket.Send( SomeString.ToCString, SomeString.length )
a temporary byte pointer is being created and passed to the function.
I'm assuming the pointer is cleaned up after the function call exits since it falls out of scope.
ToCString is a method and the returned pointer needs to be freed using MemFree
So doing something like this, that creates a temporary pointer that is passed to a function that is outside of my control is definitely a mem-leak then?
Bummer. Oh well, it's an easy enough work around.
...
So doing something like this, that creates a temporary pointer that is passed to a function that is outside of my control is definitely a mem-leak then?
Itdepends on what the pointer is pointing to.
.ToCString() doesn't simply pass a pointer to the first byte of the string though does it?
I thought it created a new byte array initialized with the data from the string + a null character, and then returned the pointer to that. If this is the case, how would I ever be able to free this new temporary byte array?
Once its sent why not just free it?
Something like:
local SomeCString:byte ptr=SomeString.ToCString()
Socket.Send( SomeCString, SomeString.length )
MemFree(SomeCString)
Azathoth: Yeah. That's basically the "workaround" I planned on using if it turned out that it was indeed a leak.
And it turned out it was - and the method you mention Az does work. I realized a bigger issue though that eluded me before - ToCString() essentially makes a copy of the string - and in this case I'd much rather just have an actual pointer to the string itself (although I can understand why BMax doesn't do it this way).
Copying large amounts of text to send is going to get expensive.
I guess I'll have to look at the source for TString and see if I can extend it and make it return a byte ptr to the internal char array.
BMax uses 16 bit unicode strings though, so ToCString not only makes a copy but converts it to 8 bit.
Hmm, looks like I might have to whip up my own string class using arrays and slicing. Might as well implement ring buffers while I'm at it ::grumble::
No. "CStrings" are garbage collected. It says so in Marks worklog somewhere.
I thought that was only if you used the $z thing?
The Description for ToCString() says
Converts a string to a null terminated sequence of 8 bit bytes. The returned memory must be freed with a call to MemFree.
Well, in Bmax 1.18 (I think that's the version I'm running at work - gotta update ), they aren't being garbage collected. Without MemFree() the memory was disappearing in all of my tests.
CStrings used to be collected before the automatic collection went in (V1.12?), now they live outside of the GC's control and have to be managed manually.
Yep. I remember adding MemFree()'s to all my mods because ToCString() wasn't freeing up its memory.
So you end up with 3 lines of code per ToCString - as per the example code snippet by Azathoth above. :-)
If you want to have managed CStrings (to yan and the rest), there is $z and $w which does manage it through the GC.
Depending on situation this one is enough. But if you need to send the cstring often, it isn't a usefully solution as the cstring is created on every call again which takes its time (mem alloc, setting data, cleanup)
Local stream:SocketStream = CreateSocketStream(socket)
stream.WriteString(some_string)
If you want to have managed CStrings (to yan and the rest)
What's the weather like in Dreamoraland at the moment?
Local stream:SocketStream = CreateSocketStream(socket)
stream.WriteString(some_string)
surely this will create a Cstring and send it as well? The underlying socket representation requires a pointer - and I can't imagine the string type giving out a pointer to it's internals which could allow the string to be corrupted.
Maybe someone can answer this and save me from looking through the source (of which the C++ stuff usually goes over my head ;)
Well, just looked up TStream.WriteString.
It simply creates a new variable, calls String.ToCString, and then memfree's the temporary byte pointer.
It simply creates a new variable, calls String.ToCString, and then memfree's the temporary byte pointer.
Thats why you use a stream and WriteString, it handles memory management for you.