c++ - WASM 链接错误 : function signature mismatch

标签 c++ emscripten 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 正在尝试使用与具有 64 位整数而不是 32 位整数的 javascript 通信的 header ,但我看不出这是怎么发生的。
我将尝试重新安装 emscripten,但即使有效,我也想更好地了解导致这种情况的原因。

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

最佳答案

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

  • 你真的不需要担心 32 位/64 位的东西。当前的 WebAssembly 规范没有 64 位机器,它只有 32 位地址(但它内部支持 64 位整数 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/

    相关文章:

    c++ - 不同的行为取决于数据

    c++ - 仅当对象不存在于 map 中时,如何使用 Rust 将新对象插入到 map 中?

    c++ - 更改 TreeView 状态图像

    javascript - 使用 Emscripten C++ Web Worker 高效传输大型数组 : which JavaScript design is better?

    C++ RapidJSON Writer 和 String Buffer 输出未知字符

    c++14 - Emscripten 和 C++14

    c++ - 使用 Emscripten 构建静态或共享的 boost 库

    python - 操作错误: foreign key mismatch

    java - 即使我使用的是 Locale.US,点也会返回 MisMatch 异常

    php - Laravel 5.1 session 中 POST header token 和 token 之间的 token 不匹配