简体   繁体   中英

Webassemly memory management and pointers

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 ie 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 ie 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 ie but instead of pointer of to chars i have pointer to uint8_t ie:

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 ie 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?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM