WASM link error: function signature mismatch

WASM link error: function signature mismatch

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

exception thrown: RuntimeError: function signature mismatch,RuntimeError: function signature mismatch

这开始发生在以前有效的代码中,似乎与 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;
}

建筑:

call emcc -o ./test.js test_file.cpp -s WASM=1 -s NO_EXIT_RUNTIME=1 -std=c++1z 

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

沿线的某个地方,我怀疑 wasm 正在尝试使用 headers 与具有 64 位整数而不是 32 位整数的 javascript 通信,但我看不出这是怎么发生的. 我将尝试 re-installing emscripten,但即使可行,我也想更好地了解导致此问题的原因。

作为变通方法,有人知道如何让 emcc 忽略对 64 位整数的担忧并默默地将它们转换为 32 位吗?毕竟,我不想处理超过 3gigs 的 ram。

你得到这个错误只是因为你的代码有误。

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

好的,让我们在本机环境中试试这个。

g++ test_file.cpp -o test.out
如果 test_file.cpp 不存在,

运行 ./test.out 将打印以下内容:

6
8
[2]    14464 segmentation fault (core dumped)  ./test.out

所以你的代码是错误的,但为什么 Emscripten 以不同的方式抛出错误?当您使用 emcc 而没有像 -g 这样的调试标志时,它将具有最小化的环境,不会捕获像段错误这样的错误,因为这种智能运行时会增加二进制文件的大小,这在 Web 环境中是至关重要的。结果,运行时保持 运行 忽略 segfualt,最终会出现随机错误。所以 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/

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

exception thrown: RuntimeError: abort(segmentation fault) at Error

现在您不会收到像签名不匹配这样的误导性错误:)

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

通过正确的--source-map-base服务器IP设置,您将获得更好的调试体验。比如你会在浏览器中获取源码test_file.cpp,这样你就可以给.cpp文件设置断点了。

祝你调试愉快:)