Сопоставление типов va_list между компиляторами

У меня есть проект, состоящий из группы динамически загружаемых модулей. Первоначально все всегда создавалось с помощью MSVC 2003, но в последнее время я работал над тем, чтобы заставить его работать с GCC. Все идет довольно гладко, за исключением одной проблемы. Для 64-битного кода GCC и MSVC не согласны с тем, что такое va_list . Для 32-битной версии все в порядке. Проблема 64-битного несоответствия возникает, когда модуль, созданный с помощью одного компилятора, имеет публичную функцию с параметром va_list , и эта функция вызывается из модуля, созданного другим компилятором.

В спецификации говорится ничего о том, что такое va_list , за пределами раздела 7.15. Переменные аргументы , параграф 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;
}
8
задан Carl Norum 29 September 2010 в 21:48
поделиться