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。
你得到这个错误只是因为你的代码有误。
- 您真的不需要担心 32 位/64 位的问题。当前的 WebAssembly 规范没有 64 位机器,它只有 32 位地址(但它在内部支持 64 位整数
i64
并且可以很好地计算 64 位整数。它只是没有 64 位地址。)
这意味着编译器已经知道目标机器是 32 位的并且 size_t
将是 32 位的。
- 在评论中,我问你是要打开文件还是要创建文件。 这很重要,因为使用
"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文件设置断点了。
祝你调试愉快:)
我已经通过 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。
你得到这个错误只是因为你的代码有误。
- 您真的不需要担心 32 位/64 位的问题。当前的 WebAssembly 规范没有 64 位机器,它只有 32 位地址(但它在内部支持 64 位整数
i64
并且可以很好地计算 64 位整数。它只是没有 64 位地址。) 这意味着编译器已经知道目标机器是 32 位的并且size_t
将是 32 位的。 - 在评论中,我问你是要打开文件还是要创建文件。 这很重要,因为使用
"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文件设置断点了。
祝你调试愉快:)