我已经通过 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 正在尝试使用与具有 64 位整数而不是 32 位整数的 javascript 通信的 header ,但我看不出这是怎么发生的。
我将尝试重新安装 emscripten,但即使有效,我也想更好地了解导致这种情况的原因。
作为一种解决方法,有没有人知道如何让 emcc 忽略对 64 位整数的担忧并默默地将它们转换为 32 位?毕竟,我不想解决超过 3gigs 的 ram。
最佳答案
您收到错误只是因为您的代码错误。
i64
并且可以很好地计算 64 位整数。它只是没有 64 位地址。)这意味着编译器已经知道目标机器是 32 位的,
size_t
也将是 32 位的。 "ra"
与 fopen()
一起使用会导致由于 r
标志而导致文件不存在时出现段错误! 好的,让我们在 native 环境中尝试一下。
g++ test_file.cpp -o test.out
如果
./test.out
不存在,运行 test_file.cpp
将打印以下内容:6
8
[2] 14464 segmentation fault (core dumped) ./test.out
所以你的代码是错误的,但为什么 Emscripten 会以不同的方式抛出错误?当您使用
emcc
而没有调试标志(如 -g
)时,它将具有最小化的环境,不会捕获诸如段错误之类的错误,因为这种智能运行时会增加二进制大小,这在网络环境中至关重要。因此,运行时会继续运行而忽略 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 文件设置断点。享受调试的乐趣:)
关于c++ - WASM 链接错误 : function signature mismatch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59765945/