Ответ 1
Несколько комментариев сказали нет, и мы можем укрепить это с небольшими рассуждениями. В наиболее знакомых ABI функции с объявлением void func(void *, int, int)
разрешено использовать регистр, в котором результат int
будет возвращен как регистр нуля; его не нужно сохранять и восстанавливать. Функция с объявлением int func(void *, int, int)
требуется , чтобы использовать регистр, в который будет возвращен результат int
. В остальном эти декларации идентичны. Поэтому машинный код любой реализации int func(void *, int, int)
также является машинным кодом, который удовлетворяет void func(void *, int, int)
.
Другими словами, вызывающий не имеет возможности отличать машинный код, который сознательно возвращает результат в регистре возврата из кода, который, как случается, оставляет в этом регистре некоторый расчет нуля.
Обратите внимание, что это рассуждение требует, чтобы вызываемая функция скрывалась за ABI; он полагается на двоичное поведение, указанное ABI. Если источник вызываемой функции отображается, когда вызываемая функция скомпилирована (или другие части реализации, которые могут повлиять на реализацию вызова), тогда оптимизация может привести к поведению, которое обходит ABI (например, соблюдая, что вызванная процедура не использует регистр возврата и поэтому использует его в вызывающем абоненте, чтобы сохранить некоторое значение, которое, как ожидается, останется неизменным по вызову).
Поскольку вы говорите, что это для общей библиотеки, вы, вероятно, безопасны: общая библиотека скомпилирована отдельно, а ее источник недоступен для ее вызывающих. Однако вы должны рассмотреть боковые каналы. Например, возможно, разделяемая библиотека является частью набора библиотек, которые обмениваются источниками и содержат межбиблиотечные вызовы. В этом случае у кого-то может быть старая версия общей библиотеки, которая была скомпилирована с представлением источника void
и новой версией разделяемой библиотеки, содержащей источник int
. (И даже для этого требуются необычные компоновки исходного кода или модные компиляторы, которые интегрируют информацию по нескольким единицам компиляции.)