Tengo un proyecto que consiste en un grupo de módulos cargados dinámicamente. Originalmente, todo estaba siempre construido con MSVC 2003, pero últimamente he estado trabajando para que funcione con GCC. Todo ha ido bastante bien, excepto por un problema. Para el código de 64 bits, GCC y MSVC no están de acuerdo con lo que es va_list
. Para 32 bits, las cosas parecen estar bien. El problema que causa la discrepancia de 64 bits es cuando un módulo creado con un compilador tiene una función pública con un parámetro va_list
y esa función se llama desde un módulo creado por el otro compilador.Coincidencia de tipos de va_list entre compiladores
La especificación no dice nada acerca de lo que un va_list
es decir, fuera de Sección 7.15 argumentos variables <stdarg.h>
, párrafo 3:
El tipo declarado es
va_list
que es un tipo de objeto adecuado para contener la información que necesitan las macros
va_start
,va_arg
,va_end
, yva_copy
.
En ese párrafo sólo significa que se trata de todas las cosas depende del compilador - es así, ¿hay una manera de hacer que estos dos compiladores están de acuerdo en el contenido de un 64-bit va_list
? Para un impacto mínimo en mi sistema, hacer que GCC coincida con el MSVC va_list
sería lo mejor, pero tomaré cualquier solución que pueda obtener.
Gracias por ayudar!
Editar:
Hice algunas pruebas de 32 bits, y no tengo problemas allí también, lo que me sorprendió ya que hay diferencias supuestamente ABI entre las plataformas Intel de 32 bits. La base de código que estoy usando MSVC define todas las macros de función variadic como:
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)
he simplificado un poco del proyecto real, pero este es el código que estaba usando para mi prueba. Con GCC, este código definitivamente no está obteniendo mis argumentos correctamente. Tal vez es solo un error, como Zack sugiere a continuación?
de nuevo Edit:
consigo resultados de trabajo para la aplicación de prueba de 32 bits que sigue con -O0
, -O0
, y -O2
, pero no -O3
, -Os
y -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;
}
Uh. Copiaste las definiciones 'va_ *' del '' de MSVC en un archivo que luego compiló con GCC, ¿o sí? Porque eso definitivamente no funcionará, y no te dice nada útil. Debe usar absolutamente el '' de GCC para definir funciones variadas compiladas con GCC (y MSVC para MSVC) o su código * será * mal compilado. –
zwol
Lo que debe hacer para esta prueba es mover 'f' a su propio archivo, reemplazar todas las definiciones de mano de' va_ * 'con' #include ', poner" 'extern int f (int n, ...) ; 'above' main' en ese archivo, compilar uno con GCC y el otro con MSVC, y vincular los dos archivos de objeto. * Eso * debería funcionar en cualquier dirección (MSVC llama a las llamadas GCC o GCC MSVC) en x32 o x64. –
zwol
Sí, funcionó bien al apagar la línea interior o al colocarla en una unidad de compilación separada. De todos modos, es un problema completamente separado de los tipos va_list que no coinciden, que como dices, es un error con el compilador –