MALOUDA-PSA 2024-04-23 15:41 采纳率: 90.9%
浏览 2
已结题

webassembly 的问题9

html:

<html>
  <head>
    <meta charset="utf-8">
    <title>Wasm:demo</title>
  </head>
  <body>
    <script>
    Module = {};
    Module.onRuntimeInitialized = function() {
        var str = 'enc_string31415';
        var strBuff = new TextEncoder().encode(str);
        var strPtr = Module._malloc(strBuff.length + 1);
        Module.HEAPU8.set(strBuff, strPtr);
        Module.HEAPU8[strPtr + strBuff.length] = 0;
        console.log('EncryptionAES:', Module._EncryptionAES("str", "aaab", "kkrr", strPtr));
        Module._free(strPtr);


c++

EMSCRIPTEN_KEEPALIVE
int EncryptionAES(const char * strSrc, const char * gkey, const char* giv, char** str) 
{
    ...  ... ... 
EM_ASM_({
        var jsStr = Pointer_stringify($0);
        jstr=jsStr;
    }, *str);

        return 1;
}


报错:

webassemencdec.wasm:0xa700 Uncaught (in promise) RuntimeError: memory access out of bounds
    at webassemencdec.wasm:0xa700
    at webassemencdec.wasm:0xa737
    at webassemencdec.wasm:0x969c
    at webassemencdec.wasm:0x12de
    at Object._EncryptionAES (webassemencdec.js:611:12)
    at Module.onRuntimeInitialized (demo.html:22:40)
    at doRun (webassemencdec.js:4732:71)
    at run (webassemencdec.js:4749:5)
    at runCaller (webassemencdec.js:4693:19)
    at removeRunDependency (webassemencdec.js:547:7)
  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-23 15:41
    关注

    引自免费微信小程序:皆我百晓生

    根据您提供的信息,错误提示是关于内存访问越界的问题。这通常发生在尝试访问的内存位置超过了分配给它的空间时。在您的C++代码中,char** str是一个指向指针的指针,但在JavaScript部分,它被赋值为一个字符串,这是不正确的。

    要解决这个问题,我们需要确保传递给C++函数的参数类型与预期一致,并且正确地处理返回的结果。首先,在C++函数中,您应该期望接收一个指向字符数组(即字符串)的指针,而不是一个指向指针的指针。然后,在JavaScript端,你需要创建一个足够的缓冲区来存储从C++函数返回的加密后的字符串。

    这里是修改后的C++和HTML代码示例:

    C++:

    #include <emscripten.h>
    
    using namespace emscripten;
    
    EMSCRIPTEN_KEEPALIVE
    int EncryptionAES(const char * strSrc, const char * gkey, const char* giv, char* strBuffer, int bufferLength) 
    {
        // ...  ... ...
        std::string encryptedStr = "encrypted string"; // 假设这是一个加密算法返回的结果
    
        if (bufferLength < encryptedStr.size() + 1) { // 添加1是因为还需要存储null终止符
            EM_ASM({ throw "Buffer too small for the encrypted string" });
        }
    
        strncpy(strBuffer, encryptedStr.c_str(), bufferLength); // 复制到C++堆栈上的字符串
        strBuffer[bufferLength - 1] = '\0'; // 添加null终止符
    
        return encryptedStr.size(); // 返回实际复制的字符数
    }
    
    // 添加一个额外的函数用于获取加密后的字符串长度
    EMSCRIPTEN_KEEPALIVE
    int getEncryptedStringLength(const char * strSrc, const char * gkey, const char* giv) 
    {
        char dummyBuffer[1024]; // 使用足够大的临时缓冲区
        return EncryptionAES(strSrc, gkey, giv, dummyBuffer, sizeof(dummyBuffer));
    }
    

    HTML:

    <html>
      <head>
        <meta charset="utf-8">
        <title>Wasm:demo</title>
      </head>
      <body>
        <script>
          Module = {};
    
          Module.onRuntimeInitialized = function() {
              var str = 'enc_string31415';
              var key = 'aaab';
              var iv = 'kkrr';
    
              // 获取加密后字符串的长度
              var encryptedStringLength = Module._getEncryptedStringLength(str, key, iv);
    
              // 分配足够的空间来存储加密后的字符串
              var strBuffer = new Array(encryptedStringLength + 1).join('\0').split('').map(char => parseInt(char.charCodeAt(0), 10)).buffer;
    
              // 进行加密操作
              var strPtr = Module._malloc(strBuffer.byteLength);
              Module.HEAPU8.set(new Uint8Array(strBuffer), strPtr);
              var encryptedSize = Module._EncryptionAES(str, key, iv, strPtr, strBuffer.byteLength);
    
              // 将加密后的字符串从C++堆栈转换回JavaScript字符串
              var encryptedStr = Pointer_stringify(Module.HEAPU8.subarray(strPtr, strPtr + encryptedSize));
    
              Module._free(strPtr);
    
              console.log('EncryptionAES:', encryptedStr);
          };
        </script>
      </body>
    </html>
    

    在这个修复方案中,我们添加了一个新的辅助函数getEncryptedStringLength,用于计算加密后字符串的长度。然后,我们根据这个长度分配一个JavaScript缓冲区。在加密完成后,我们将加密后的字符串从C++堆栈复制回JavaScript并打印出来。这样就解决了内存访问越界的错误。注意,这里的代码只是一个基本示例,实际的加密函数需要替换为你实际的加密实现。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 5月1日
  • 已采纳回答 4月23日
  • 已采纳回答 4月23日
  • 创建了问题 4月23日

悬赏问题

  • ¥15 孟德尔随机化结果不一致
  • ¥15 深度学习残差模块模型
  • ¥50 怎么判断同步时序逻辑电路和异步时序逻辑电路
  • ¥15 差动电流二次谐波的含量Matlab计算
  • ¥15 Can/caned 总线错误问题,错误显示控制器要发1,结果总线检测到0
  • ¥15 C#如何调用串口数据
  • ¥15 MATLAB与单片机串口通信
  • ¥15 L76k模块的GPS的使用
  • ¥15 请帮我看一看数电项目如何设计
  • ¥23 (标签-bug|关键词-密码错误加密)