У меня есть проект, который состоит из группы динамически загружаемых модулей.Первоначально все было построено с MSVC 2003, но в последнее время я работаю над тем, чтобы заставить его работать с GCC.Все прошло довольно гладко, за исключением одной проблемы.Для 64-битного кода GCC и MSVC не согласны с тем, что такое va_list
.Для 32-битной системы все выглядит нормально.Проблема, которую вызывает 64-разрядное несоответствие, заключается в том, что модуль, созданный с помощью одного компилятора, имеет открытую функцию с параметром va_list
, и эта функция вызывается из модуля, созданного другим компилятором.
В спецификации ничего не сказаноо том, что такое va_list
, вне Раздел 7.15 Переменные аргументы <stdarg.h>
, абзац 3:
Заявленный тип:
va_list
, который является типом объекта, подходящим для хранения информации, необходимой макросам va_start
, va_arg
, va_end
и va_copy
.
Этот абзац просто означает, что все это зависит от компилятора - так, есть ли способ заставить эти два компилятора согласовать содержимое64-битного va_list
?Для наименьшего воздействия на мою систему лучше всего было бы сделать так, чтобы GCC соответствовал MSVC va_list
, но я приму любое решение, которое смогу получить.
Спасибо за помощь!
Редактировать:
Я провел 32-битное тестирование, и у меня там тоже есть проблемы, что меня удивило, так как якобы нет различий ABI между любыми 32-битными платформами Intel.Кодовая база MSVC, которую я использую, определяет все макросы переменных функций следующим образом:
typedef char *va_list;
#define intsizeof(n) ((sizeof(n) + sizeof(int) - 1) &~(sizeof(int) - 1))
#define va_start(ap, v) (ap = (va_list)&(v) + intsizeof(v))
#define va_arg(ap, t) (*(t *) ((ap += intsizeof(t)) - intsizeof(t)))
#define va_end(ap) (ap = (va_list)0)
Я немного упростил реальный проект, но это код, который я использовал для своего теста.С GCC этот код определенно не получает мои аргументы.Может быть, это просто ошибка, как советует Зак ниже?
Редактировать еще раз:
Я получаю результаты работы для следующего 32-разрядного тестового приложения с -O0
, -O0
и -O2
, но не -O3
, -Os
и -Oz
:
typedef char *va_list;
#define intsizeof(n) ((sizeof(n) + sizeof(int) - 1) &~(sizeof(int) - 1))
#define va_start(ap, v) (ap = (va_list)&(v) + intsizeof(v))
#define va_arg(ap, t) (*(t *) ((ap += intsizeof(t)) - intsizeof(t)))
#define va_end(ap) (ap = (va_list)0)
int printf(const char *format, ...);
int f(int n, ...)
{
int r = 0;
va_list ap;
va_start(ap, n);
while (n--)
r = va_arg(ap, int);
va_end(ap);
return r;
}
int main(int argc, char **argv)
{
int r;
r = f(1, 1, 2, 3, 4, 5);
printf("%x\n", r);
r = f(2, 1, 2, 3, 4, 5);
printf("%x\n", r);
r = f(3, 1, 2, 3, 4, 5);
printf("%x\n", r);
r = f(4, 1, 2, 3, 4, 5);
printf("%x\n", r);
r = f(5, 1, 2, 3, 4, 5);
printf("%x\n", r);
return 0;
}