WASM链接错误:函数签名不匹配

Lut*_*her 5 c++ mismatch emscripten

我已经通过 emscripten 使用 WASM 几个星期了,并且取得了良好的进展,直到出现此错误:

exception thrown: RuntimeError: function signature mismatch,RuntimeError: function signature mismatch
Run Code Online (Sandbox Code Playgroud)

这种情况开始发生在以前可以工作的代码中,似乎与 WASM 缺乏对 javascript 中 64 位整数的支持以及文件管理中使用的偏移量有关。我做了一个孤立的案例:

#include <iostream>

int main(int argc, char const *argv[])
{   
    char test[30];
    std::cout << __LINE__ << std::endl;
    FILE *f = fopen("minimal_call_dispatch.cpp","ra");
    std::cout << __LINE__ << std::endl; 
    fseek(f, 100, SEEK_SET);
    std::cout << __LINE__ << std::endl;
    fclose(f);
    std::cout << __LINE__ << std::endl; 
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

建筑:

call emcc -o ./test.js test_file.cpp -s WASM=1 -s NO_EXIT_RUNTIME=1 -std=c++1z 
Run Code Online (Sandbox Code Playgroud)

由于上述错误,在“fseek”失败之前会输出“6\n8\n”。

在此过程中,我怀疑 wasm 正在尝试使用与具有 64 位整数而不是 32 位整数的 javascript 进行通信的标头,但我不明白这是如何发生的。我将尝试重新安装 emscripten,但即使有效,我也想更好地了解导致此问题的原因。

作为解决方法,有人知道如何让 emcc 忽略对 64 位整数的担忧并默默地将它们转换为 32 位吗?毕竟,我不想讨论超过 3G 的内存。

Bum*_*Kim 5

您收到错误只是因为您的代码错误。

  1. 您真的不需要担心 32 位/64 位的问题。当前的 WebAssembly 规范没有 64 位机器,并且只有 32 位地址(但它i64内部支持 64 位整数,并且可以很好地计算 64 位整数。它只是没有 64 位地址。)这意味着编译器已经知道目标机器是 32 位并且size_t将会是 32 位。
  2. 在评论中,我询问您是要打开该文件还是要创建该文件。这很重要,因为当文件因标志不存在时,使用"ra"with会导致分段错误!fopen()r

好的,让我们在本机环境中尝试一下。

g++ test_file.cpp -o test.out
Run Code Online (Sandbox Code Playgroud)

如果不存在,运行./test.out将打印以下内容:test_file.cpp

6
8
[2]    14464 segmentation fault (core dumped)  ./test.out
Run Code Online (Sandbox Code Playgroud)

所以你的代码是错误的,但为什么 Emscripten 会以不同的方式抛出错误?当您在emcc不使用诸如 之类的调试标志的情况下使用-g时,它将具有最小化的环境,不会捕获诸如段错误之类的错误,因为这种智能运行时会增加二进制文件的大小,这在 Web 环境中至关重要。因此,运行时会忽略段而继续运行,最终会出现随机错误。所以function signature mismatch没有什么意义。

您可以使用与调试相关的选项来构建它:

emcc -o ./test.html  test_file.cpp -s WASM=1 -std=c++1z \
    -g4 -s ASSERTIONS=2 -s SAFE_HEAP=1 -s STACK_OVERFLOW_CHECK=1 \
    --source-map-base http://your_server_ip:port/
Run Code Online (Sandbox Code Playgroud)

然后打开test.html你现在会看到正确的错误:

exception thrown: RuntimeError: abort(segmentation fault) at Error
Run Code Online (Sandbox Code Playgroud)

现在您将不会遇到诸如签名不匹配之类的误导性错误:)

顺便说一句,替换fopen("minimal_call_dispatch.cpp","ra");fopen("minimal_call_dispatch.cpp","a");将修复错误。

正确--source-map-base设置服务器IP,您将获得更好的调试体验。例如,您将test_file.cpp在浏览器中获取源代码,以便可以在 .cpp 文件中设置断点。

享受调试的乐趣:)