Ho un progetto costituito da un gruppo di moduli caricati in modo dinamico. Originariamente, tutto era sempre stato realizzato con MSVC 2003, ma ultimamente ho lavorato per farlo funzionare con GCC. Tutto è andato abbastanza bene, tranne che per un problema. Per il codice a 64 bit, GCC e MSVC non sono d'accordo su cosa sia uno va_list
. Per 32 bit, le cose sembrano andare bene. Il problema delle mancate corrispondenze a 64 bit è quando un modulo creato con un compilatore ha una funzione pubblica con un parametro va_list
e tale funzione viene chiamata da un modulo creato dall'altro compiler.Tipi di va_list corrispondenti tra i compilatori
Le specifiche non dice nulla su ciò che un va_list
è, al di fuori di Sezione 7.15 argomenti variabili <stdarg.h>
, comma 3:
Il tipo dichiarato è
va_list
che è un tipo di oggetto adatto per contenere le informazioni necessarie per le macro
va_start
,va_arg
,va_end
, eva_copy
.
Questo punto significa che solo questa è tutta roba dipende compilatore - è così, c'è un modo per rendere questi due compilatori d'accordo sul contenuto di un 64-bit va_list
? Per il minore impatto sul mio sistema, fare in modo che GCC corrisponda al MSVC va_list
sarebbe il migliore, ma prenderò qualsiasi soluzione che possa ottenere.
Grazie per l'aiuto!
Edit:
ho fatto dei test a 32 bit, e non ho problemi anche lì, che mi ha sorpreso in quanto non vi sono presumibilmente differenze tra ABI eventuali piattaforme Intel a 32 bit. La base di codice MSVC sto usando definisce tutte le macro funzione variadic come:
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)
Ho semplificato un po 'dal vero e proprio progetto, ma questo è il codice che stavo usando per la mia prova. Con GCC, questo codice sicuramente non sta ottenendo correttamente i miei argomenti. Forse è solo un bug, come suggerisce Zack di seguito?
Edit ancora:
ottengo risultati di lavoro per la seguente applicazione di test a 32 bit con -O0
, -O0
, e -O2
, ma non -O3
, -Os
, e -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. Hai copiato le definizioni 'va_ *' da MSVC '' in un file che hai poi compilato con GCC, è così? Perché sicuramente non funzionerà e non ti dirà niente di utile. È assolutamente necessario utilizzare GCC "" per definire le funzioni variadiche compilate con GCC (e MSVC per MSVC) o il proprio codice * sarà errato. –
zwol
Quello che devi fare per questo test è spostare 'f' sul proprio file, sostituire tutte le definizioni di mano di' va_ * 'con' #include ', inserisci" 'extern int f (int n, ...) ; 'sopra' main' in quel file, compila uno con GCC e l'altro con MSVC, e collega i due file oggetto. * Che * dovrebbe funzionare in entrambe le direzioni (MSVC chiama GCC o GCC chiama MSVC) su x32 o x64. –
zwol
Sì, ha funzionato bene quando si disattivava l'inlining o quando lo si inseriva in un'unità di compilazione separata, ma è un problema completamente separato dai tipi di va_list non corrispondenti, che, come dici tu, è un bug con il compilatore –