Ошибка ссылки WASM: несоответствие сигнатуры функции

Я использую 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, но даже если это сработает, я хотел бы лучше понять, в чем причина.

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


person Luther    schedule 16.01.2020    source источник
comment
Почему вы упоминаете 64-битный int, когда код ничего не делает с 64-битным?   -  person Bumsik Kim    schedule 16.01.2020
comment
А где твой minimal_call_dispatch.cpp, который ты открываешь? Вы открываете файл, который вы отправили, или вы создаете файл?   -  person Bumsik Kim    schedule 16.01.2020
comment
Имя файла здесь не имеет значения: оно может быть любым. Этот файл был просто чем-то в моем рабочем каталоге. 64-битная проблема — это предположение о том, что я думаю, может быть проблемой, потому что видел, как у других возникают проблемы с 64-битной связью функций int и wasm. Я подозреваю, что по какой-то причине код считает, что «size_t» является «длинным длинным» 64-битным целым числом (как при сборке С++ для 64-битного), а не 32-битным значением. Проблема в том, что WASM ругается, когда доходит до fseek, и я хотел бы знать, есть ли у кого-нибудь еще эта проблема, и если да, то как они ее исправили.   -  person Luther    schedule 16.01.2020
comment
Нет, файл имеет значение. Вы ожидаете, что файл будет создан, или вы открываете существующий файл в этом коде. Я уже получил ответ, но прежде чем публиковать ответ, я узнаю, чего вы действительно ожидаете от кода.   -  person Bumsik Kim    schedule 16.01.2020
comment
В некоторых реализациях fseek смещение указывается как «длинное целое число», что может вызвать проблемы для WASM. Одна вещь, которую я сделал примерно в то время, когда он перестал работать, — это попытался создать make-файл для проекта, а не делать все из одной строки. Эта попытка не удалась: какая-то неясная ошибка в файле python о поиске интерпретаторов, поэтому я пока отказался от этой банки червей, но, возможно, он где-то повредил какой-то файл emscripten, заставив его получить заголовки C из другого места, один с 'long int ' в реализации fseek? Это только догадки, кстати.   -  person Luther    schedule 16.01.2020
comment
на самом деле это не так. Создайте еще один файл, назовите его bob.txt, это действительно не главное здесь :)   -  person Luther    schedule 16.01.2020
comment
Давайте продолжим это обсуждение в чате.   -  person Luther    schedule 16.01.2020


Ответы (1)


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

  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.out напечатает следующее, если test_file.cpp не существует:

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

Итак, ваш код неверен, но почему Emscripten выдает ошибку по-другому? Когда вы используете emcc без флагов отладки, таких как -g, у него будет минимизированная среда, которая не перехватывает такие ошибки, как segfault, потому что такая интеллектуальная среда выполнения увеличит размер двоичного файла, который имеет решающее значение в веб-среде. В результате среда выполнения продолжает работать, игнорируя segfult, и в конечном итоге это приведет к случайной ошибке. Так что 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"); исправит ошибку.

С правильными настройками IP-адреса сервера --source-map-base у вас будет лучший опыт отладки. Например, вы получите исходный код test_file.cpp в браузере, чтобы установить точки останова в файле .cpp.

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

person Bumsik Kim    schedule 16.01.2020
comment
Спасибо за ответ, но этот файл действительно существует на моем компьютере — я прохожу мимо «fopen», а затем происходит сбой при «fseek» из-за вызова «несоответствие сигнатуры функции». Что касается --source-map-base - да, это то, что я действительно хочу заставить работать, но, похоже, на данный момент это не работает с набором инструментов emscripten. Очевидно, это работает с альтернативой «Cheerp», но я еще не пробовал (одна проблема за раз :) - person Luther; 16.01.2020
comment
Хм... -- source-map-base работает на моей машине. Вы запускаете его в веб-браузере или в nodejs? Если это веб-среда, вы получите чистую файловую систему в браузере с нулевыми файлами, потому что браузер не может получить файл с вашего компьютера. - person Bumsik Kim; 16.01.2020
comment
См. раздел «Файлы упаковки» в документации. конкретные файловые API из-за ограничений веб-среды. - person Bumsik Kim; 16.01.2020
comment
Я запускаю через браузер и использую упаковщик файлов, но, подумав об этом, я не думаю, что этот конкретный тестовый файл был включен в него, хотя ошибка была такой же, как и в моем основном проекте (который больше и более громоздки в работе, отсюда и этот минимальный тест). Сегодня попробую еще раз (сейчас я не на этой машине). Я также рассмотрю --source-map-base, хотя проблема, с которой я столкнулся, заключалась в создании исходных карт для начала - похоже, emcc не хотел их генерировать. - person Luther; 16.01.2020
comment
Все, извините, беру все назад: меня выкинуло сообщение об ошибке. Я правильно создал файл данных для теста, и он работал нормально. У меня даже работает сопоставление исходников: скорее всего, это не работает в моем основном проекте, потому что он довольно большой. Спасибо за помощь. - person Luther; 16.01.2020
comment
хотя в моем основном проекте проблема остается - и она также проходит проверку «if (file != NULL)». Ну ладно, вернемся к исходной точке :/ - person Luther; 16.01.2020