Как правильно пересылать нешаблонные аргументы с переменным числом аргументов в C/C++ под MSVCC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как правильно пересылать нешаблонные аргументы с переменным числом аргументов в C/C++ под MSVC

Сообщение Anonymous »

Я пытаюсь пересылать нешаблоновые аргументы с переменным числом аргументов между двумя функциями. Ни одна из этих функций не принадлежит мне, поэтому я не могу изменить их подписи. Для этой цели я использовал va_args, но (к сожалению) мое решение не работает должным образом под MSVC. Вероятно, из-за перекрытия стека я получаю случайное значение, выбранное из стека.
Вот минимальный пример, воспроизводящий мою проблему. Функции funcA и funcB имеют ту же сигнатуру, что и функции из моей исходной задачи.
#include

int funcA(int a, void* b, ...)
{
va_list args;
va_start(args, b);
auto value = a + va_arg(args, int);
va_end(args);
return value;
}

int funcB(int a, void* b, ...)
{
va_list args;
va_start(args, b);
auto value = funcA(a, args);
va_end(args);
return value;
}

int main() {
return funcB(2, nullptr, 163);
}

Возможный вывод GCC:
Program returned: 165

Возможный вывод MSVC:
Program returned: 7731509

Вы можете запустить этот код здесь https://godbolt.org/z/Mjc8E3onW
Вышеупомянутое решение работает правильно и, как и ожидалось, в GCC, но в MSVC этот код возвращает мусорное число.
Я пытался настроить этот минимальный пример, явно определив соглашение о вызовах для __cdecl, но это не помогло. Я также пытался скомпилировать его, используя разные флаги оптимизации, но это ничего не изменило;
Обратите внимание, что я видел здесь много похожих вопросов, но ни один из них не ответил на мой вопрос, связанный с в MSVC.
Я проверил, как функция printf пересылает эти аргументы, но, к сожалению, она передает их в _vfprintf_s_l с помощью va_list, и это то, что я В моем случае не могу сделать.
_Check_return_opt_
_CRT_STDIO_INLINE int __CRTDECL _printf_s_l(
_In_z_ _Printf_format_string_params_(0) char const* const _Format,
_In_opt_ _locale_t const _Locale,
...)
#if defined _NO_CRT_STDIO_INLINE
;
#else
{
int _Result;
va_list _ArgList;
__crt_va_start(_ArgList, _Locale);
_Result = _vfprintf_s_l(stdout, _Format, _Locale, _ArgList);
__crt_va_end(_ArgList);
return _Result;
}
#endif

EDIT
Параметр b здесь auto value = funcA(a, args); был удален намеренно чтобы протестировать его под GCC. Даже если я верну его обратно, он не будет работать ни под GCC, ни под MSVC.
Моя настоящая/исходная проблема связана с перехватом функций. Мне нужно поместить перехватчик в функцию, экспортируемую .dll, с таким вариационным интерфейсом. Итак, когда я это делаю, я получаю код, который выглядит примерно так:
// orig::exported_func
// this is the original function exported by the .dll
// I don't have access to its implementation
//
// hook::exported_func
// this is my stub hook function. The hook is placed in runtime,
// by overriding the original function asm code. After hooking,
// original function address is stored inside orig::exported_func.
int hook::exported_func(int a, void* b, ...) {
// here is the place I need to forward this variadic arguments
// I dont even need to read them, the thing it to pass proper stack size
// Line below is just and example, it wont compile
auto retVal = orig::exported_func(a, b, ...);
.
.
.
// do some not related staff
.
.
.
return retVal;
}


Подробнее здесь: https://stackoverflow.com/questions/792 ... under-msvc
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»