为什么Emscripten似乎此代码内存泄漏

时间:2018-09-11 09:15:43

标签: javascript memory-management memory-leaks emscripten webassembly

我已经为此工作了好几天,但找不到原因。 我编写一个c代码“ 1.c”,然后将其编译为1.js和1.wasm。然后我写2.js来调用1.js,然后再写3.js来调用2.js。但是当我运行3.js时,内存最多要超过2GB(应该小于500M),并且内存随时间增长。我使用了heapdump,它表明堆的总容量很小,但rss大于1.5 GB。我已经反复检查了我的代码,而且我认为我释放了内存。

这是我的代码。 <1.c> 我用

emcc  -s WASM=1  -s BINARYEN_ASYNC_COMPILATION=0 -s ALLOW_MEMORY_GROWTH=1 -s EXPORT_NAME="WASMModule" -s EXPORTED_FUNCTIONS="['_test_string_1','_malloc','_free']" -s  EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap","getValue","stringToUTF16","UTF16ToString"]'  -s MODULARIZE=1 -s 'EXPORT_NAME="MyWASMCode"' 1.c -o 1.js

编译1.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *test_string_1(const void *s1, int len1, const void *s2, int len2,int* out_len,int* statuscode);

void *test_string_1(const void *s1, int len1, const void *s2, int len2,int* out_len,int* statuscode) {
  void *out = malloc(len1 + len2);
  memcpy(out, s1, len1);
  memcpy(out + len1, s2, len2);
  *out_len=len1+len2;
  *statuscode=0;
  return out;
}

int main() {
  char *s1 = "hello";
  char *s2 = "world";
  int out_len=0;
  int statuscode=-1;
  char *s3 = test_string_1(s1, 5, s2, 6,&out_len,&statuscode);
  printf("%s\n%d\n%d\n", s3,out_len,statuscode);
  free(s3);
  return 0;
}

<2.js>

const MyWASMCode=require('./1.js')
let wasminstance=MyWASMCode()


function test1(str1,str2){
  let ret3= wasminstance.then(function(WASMModule){
      let buffer1 = WASMModule._malloc(str1.length*2);
      let buffer2 = WASMModule._malloc(str2.length*2);
      let p_out_len = WASMModule._malloc(4);
      let p_statuscode = WASMModule._malloc(4);

      WASMModule.stringToUTF16( str1, buffer1, str1.length*2+2);
      WASMModule.stringToUTF16( str2, buffer2, str2.length*2+2);
   let result = WASMModule._test_string_1(buffer1,str1.length*2,buffer2,str2.length*2,p_out_len,p_statuscode);
   let out_len= WASMModule.getValue(p_out_len, 'i32')
   let statuscode= WASMModule.getValue(p_statuscode, 'i32')

   let  result2=WASMModule.UTF16ToString(result);

   WASMModule.my_result=result2

   WASMModule._free(result);
   WASMModule._free(buffer1);
   WASMModule._free(buffer2);
   WASMModule._free(p_out_len);
   WASMModule._free(p_statuscode);
   // }
  })
  return ret3.my_result;
}

module.exports={test1};

<3.js>

const fs = require('fs');
const test=require('./2.js');

/*
a.txt and b.txt is both 100000 lines,and a.txt is 150m and b.txt is 50m
*/
let lines1 = fs.readFileSync('./a.txt', 'utf-8')
    .split('\n')
    .filter(Boolean);
let lines2 = fs.readFileSync('./b.txt', 'utf-8')
    .split('\n')
    .filter(Boolean);

for(let j=0;j<10;j++){
  for(let i=0;i<100000;i++){
    let ret_3=test.test1(lines1[i],lines2[i]);
    }
}

当我运行3.js时 enter image description here

,并且当j较大时,内存会增加。 和堆转储: enter image description here 这是内存泄漏吗?还是我的代码有问题?

1 个答案:

答案 0 :(得分:0)

缓冲区溢出似乎破坏了用于malloc / free的数据。

  // N*UTF-16 string + a null terminator
  let buffer1 = WASMModule._malloc(str1.length*2+2);
  let buffer2 = WASMModule._malloc(str2.length*2+2);