Исправленный код может работать
Если func_t
будет определен с использованием той же сигнатуры, что и func()
, все будет в порядке, поскольку произвольное значение b никогда не разыменовывается:
typedef bool (func_t)(int const& a, void* const& b, VExtension* const& v);
См. демо .
Но ваш код не может, поэтому здесь происходит что-то подозрительное
Ваш код, кажется, компилируется, по крайней мере, судя по трассировке времени выполнения, которую вы отобразили.Но в соответствии с опубликованными вами фрагментами код вообще не должен компилироваться.Поэтому я подозреваю, что вашим различным заголовкам удалось создать опасную смесь, используя разные определения из func_t
в разных единицах компиляции.Если это так, вы окажетесь в мире неопределенного поведения.
Например, тип возвращаемого значения int
не соответствует типу возвращаемого значения bool
.Но гораздо более пагубно, что в func_t
параметры являются простыми значениями, тогда как в func()
все они являются ссылками.Поэтому, если компилятор обманут, соглашение о вызовах, используемое вызывающим func()
, будет несовместимо с соглашениями о вызовах, используемыми func()
, что приведет к недопустимому доступу к памяти (скорее всего - но это будет зависеть от реализации -сгенерированный вызывающий код будет отправлять аргументы значений, но сгенерированный принимающий код будет ожидать, что эти параметры будут указателями на значения, и попытаться получить доступ к указанным ячейкам памяти, что будет недопустимым).
Дополнительное замечание
Теперь я не адвокат по языку, но также интересно увидеть функцию, использующую соглашение о вызовах C (extern "C"
), использующую параметры и возвращаемые типы, которые делаютне существует в C (т. е. bool и ссылки).
Дополнительные сведения
Просмотр кода сборки , сгенерированного для extension_init
на одном компиляторе с использованием исправленного определения func_t
:
lea rdx, [rsp+8] ; load effective address of third paramvalue
lea rsi, [rsp+24] ; load effective address of second param value
mov QWORD PTR [rsp+24], 7 ; initialize value
lea rdi, [rsp+20] ; load effective address of first param value
mov DWORD PTR [rsp+20], 1 ; initilize value
call rax
Если использует исходное определение , сгенерированный код выглядит иначе:
; the third value was left out by the global initializer
; but it was previously set with an LEA to load the effective
; address of the struct.
mov esi, 7 ; pass the second value
mov edi, 1 ; pass the first value
call rax