C для WebAssembly не удается при индексировании указателя - PullRequest
0 голосов
/ 21 февраля 2020

Я экспериментирую с C для WebAssembly. Но я не могу понять следующее:

int atAddressN(unsigned int idx) {
  unsigned int* intptr = 0;
  return intptr[idx];
}

int atAddress2(unsigned int idx) {
  unsigned int* intptr = 0;
  return intptr[2];
}

В результате получается следующее значение wasm / wat:

(module
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "atAddressN" (func $atAddressN))
 (export "atAddress2" (func $atAddress2))
 (func $atAddressN (; 0 ;) (param $0 i32) (result i32)
  (unreachable)
  (unreachable)
 )
 (func $atAddress2 (; 1 ;) (param $0 i32) (result i32)
  (i32.load offset=8
   (i32.const 0)
  )
 )
)

Итак, вторая функция в порядке, но первая просто приводит к (unreachable). Должен ли я сделать что-то еще, чтобы компилировать нормально?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2020

Создайте контрольный пример, который вызывает функцию, скомпилируйте с символами отладки -g и выполните отладчик, например gdb. Вот типичный сеанс отладки.

Программа получила сигнал SIGSEGV, Ошибка сегментации. 0x0000000000401147 в atAddressN (idx = 3) в e. c: 4 4 return intptr [idx];

(gdb) print intptr[idx]
Cannot access memory at address 0xc

Команда gdb print выявляет проблему.

В тестировании WebAssembly не так много особенного. Эти дети тестов, как правило, также скомпилируются как исполняемые файлы.

//test.c
int main (){ printf("int 3 is %i\n", atAddressN(3)); return 0;}
0 голосов
/ 21 февраля 2020

Разыменование нулевого указателя, похоже, действительно проблема, изменение на:

int atAddressN(unsigned int* intptr, unsigned int idx) {
  return intptr[idx];
}

int atAddress2(unsigned int* intptr, unsigned int idx) {
  return intptr[2];
}

приводит к

(module
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "atAddressN" (func $atAddressN))
 (export "atAddress2" (func $atAddress2))
 (func $atAddressN (; 0 ;) (param $0 i32) (param $1 i32) (result i32)
  (i32.load
   (i32.add
    (get_local $0)
    (i32.shl
     (get_local $1)
     (i32.const 2)
    )
   )
  )
 )
 (func $atAddress2 (; 1 ;) (param $0 i32) (param $1 i32) (result i32)
  (i32.load offset=8
   (get_local $0)
  )
 )
)

Я просто вызову функцию с 0 в качестве тогда первый аргумент.

...