Reputation: 2300
I am using webassembly in order to do some calculation using a standard library. In webassembly we can pass only 32bit integers and 64 bits integers. That means that we can pass pointers to arrays as well. That's how we are able to return strings as an array of characters i.e. example
char* EMSCRIPTEN_KEEPALIVE returnStringCharacterArray()
{
string stringToReturn = "I am learning web assembly";
char* char_array = new char [stringToReturn.length()+1];
strcpy (char_array, stringToReturn.c_str());
char* arrayPtr = &char_array[0];
// delete [] char_array;
return arrayPtr;
}
Notice the operator "new" in that function. And notice how " delete [] char_array;
" is never called there. Does that mean that if i forget to call a delete here there is memory leak here? I notice a very strange thing here. If i do call delete on the array then this example is still working!!! That means i am able to consume the string (in bought scenarios i.e. with delete and without) in java script like that:
var ptr = Module._returnStringCharacterArray();
var ptr = new Uint8Array(Module.HEAPU8.buffer, ptr, length);
var theStringObj = new TextDecoder('utf8').decode(ptr);
console.log(newstring)
What happens with "char_array" during the next function call if delete is call on it and if not? Why i am still able to consume the string even when " delete [] char_array;
" was called?
The reason i am asking this is because i have very similar situation with a vector i.e. but instead of pointer of to chars i have pointer to uint8_t i.e.:
const vector<uint8_t>& someString;
and when i try to send the pointer, poiting to the first value of the vector back to java script i.e. like this
const uint8_t* wasmVectorArrayRecostructedPtr = &someString[0];
uint8_t* nonConstBufferReconstructed = const_cast<uint8_t*>(wasmVectorArrayRecostructedPtr);
char* charArrayPtrCasted = (char*) nonConstBufferReconstructed;
then i get some random garbage instead of the string. At first I was thinking that this is because the vector is "automatically" cleaned since it is "living" on the stack, in contrary to the "char_array" which is "living" on the heap (free store). But that does not seems to be the case. What i am missing here.
How can i manually free the memory that was dynamically allocated here with the new operator after it has been consumed by javaScript .
Module._free(ptr);
does not seems to be working. How can i make sure that the "char_array" object is cleaned and it's memory is freed after being consumed by JavaScript?
Upvotes: 1
Views: 1498
Reputation: 332
I think you should have another function from JavaScript to Wasm informing the wasm module it could free the memory backing the string, and inside that function calling delete to free the linear memory that would otherwise be held.
Something like:
void EMSCRIPTEN_KEEPALIVE freeMemory(char* ptr)
{
delete [] ptr;
}
Otherwise you will keep instantiating a bunch of bytes at every call, leaking memory along the way.
This has nothing to do with the fact that Wasm memory is only growable. Memory leaks should still taken care of.
Upvotes: 0
Reputation: 4912
WebAssembly memory can grow, but never shrink. delete
allows memory to be overwritten, but it remains reserved for future use by your WebAssembly application.
when i try to send the pointer, poiting to the first value of the vector back to java script
then i get some random garbage instead of the string.
JavaScript doesn't understand the vector
type.
Upvotes: 1