Ошибка ссылки WASM: несоответствие сигнатуры функции - PullRequest
1 голос
/ 16 января 2020

Я использую WASM через emscripten уже несколько недель и добивался хорошего прогресса, до появления этой ошибки:

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

Это начало происходить в коде, который ранее работал и, кажется, что-то делать с WASM отсутствие поддержки 64-битных целых чисел в javascript и смещения, используемые в управлении файлами. Я сделал отдельный случай:

#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 

, которая выводит «6 \ n8 \ n» до сбоя «fseek» из-за указанной ошибки.

Где-то на этом пути, я подозреваю, что wasm пытается использовать заголовки, которые связываются с javascript, которые имеют 64-битные целые числа вместо 32-битных, но я не вижу, как это могло произойти. Я собираюсь попробовать переустановить emscripten, но даже если это сработает, я хотел бы получить лучшее представление о том, что вызывает это.

Как обходной путь, кто-нибудь знает, как получить их cc игнорировать заботы о 64-битных целых числах и тихо конвертировать их в 32-битные? В конце концов, я не собираюсь адресовать больше 3 гигабайт памяти.

1 Ответ

1 голос
/ 16 января 2020

Вы получили ошибку просто потому, что ваш код неправильный.

  1. Вам действительно не нужно беспокоиться о 32-битных / 64-битных вещах. Текущая версия WebAssembly c не имеет 64-разрядного компьютера и имеет только 32-разрядные адреса (но поддерживает внутреннее 64-разрядное целое число i64 и хорошо рассчитывает 64-разрядные целые числа. Просто не имеет 64- битовые адреса.) Это означает, что компилятор уже знает, что целевой компьютер является 32-разрядным, и size_t будет 32-разрядным, как будет.
  2. В комментариях я спросил, хотите ли вы открыть файл или хотите создать файл. Это важно, потому что использование "ra" с fopen() вызовет ошибку сегментации, когда файл не существует из-за флага r!

Хорошо, давайте попробуем это в собственной среде.

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, у него будет минимизированная среда, которая не перехватывает ошибки, такие как segfault, потому что такая интеллектуальная среда выполнения увеличит размер двоичного файла, который является критическим в веб-среде. В результате среда выполнения продолжает работать, игнорируя 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.

Получайте удовольствие от отладки:)

...