va_args und 64 bit
Ich bin der lead-dev für Bitfighter, und habe Probleme die Portierung des Spiels auf 64-bit-Linux. Dies sollte eine relativ einfache und häufiges problem, aber es hat überfragt einer Reihe von Menschen, und ich finde keine guten Informationen darüber.
[[ Der code wird kompiliert in 32-bit mit gcc version 4.1.2, und andere, und schlägt mit mehreren Varianten von 64-bit-Linux, aber ich verlasse mich auf Berichte von anderen, und nicht die genaue version von gcc, die fehlschlägt. Aber es nicht für mehrere Personen, auf einer Vielzahl von Linux-Geschmacksrichtungen. Ich bin 99% sicher, dies ist nicht eine compiler-version Problem. ]]
Habe ich Folgendes:
void UserInterface::drawCenteredString(int y, int size, const char *format, ...)
{
va_list args;
va_start(args, format);
char buffer[2048];
dVsprintf(buffer, sizeof(buffer), format, args);
va_end(args);
drawCenteredString2(y, size, buffer);
}
//Elsewhere, in platform.cpp... (this is where the error occurs)
S32 dVsprintf(char *buffer, int bufferSize, const char *format, void *arglist)
{
return vsnprintf(buffer, bufferSize, format, (char *) arglist);
}
Dies funktioniert gut auf 32-bit-Plattformen. Allerdings, wenn ich es kompilieren auf 64-bit-Linux schlägt fehl:
platform.cpp:457: error: cannot convert 'char*' to '__va_list_tag*' for argument '4' to 'int TNL::vsnprintf(char*, size_t, const char*, __va_list_tag*)'
Habe ich versucht, viele Varianten, einschließlich:
return vsnprintf(buffer, bufferSize, format, (va_list) arglist);
ohne Erfolg.
Hat jemand irgendwelche Ideen, wie man dieses Konstrukt tragbar, oder das gleiche zu erreichen endet mit einem mehr von 64-bit-freundliche Mechanismus?
Sowie, für bonus-Punkte 🙂 kann mir jemand sagen wo die va_list_tag Dingens kommt?
Dank!
============================================
Hier ist die Lösung ließen wir uns auf, ein anderes Beispiel:
logprintf("Hello %s", name);
Anrufe
void logprintf(const char *format, ...)
{
va_list s;
va_start( s, format );
logger(LogConsumer::GeneralFilter, format, s);
va_end(s);
}
Anrufe
void logger(LogConsumer::FilterType filtertype, const char *format, va_list args)
{
char buffer[4096];
vsnprintf(buffer, sizeof(buffer), format, args);
Platform::outputDebugString(buffer);
}
- Könnten Sie bitte Informationen hinzufügen, die angibt, welche Zeile es ist, wo der Fehler Auftritt? Im inneren Benutzeroberfläche::drawCenteredString oder innerhalb dVsprintf? Bitte auch hinzufügen, was compiler (genaue version) und welches Betriebssystem (linux), die Sie verwenden.
- Ich veränderte die Frage zu klären, dass der Fehler Auftritt, wo dVsprintf() definiert ist.
- auf einigen 64-bit-Implementierungen
va_list
ist nicht nur Zeiger auf den stack ist, wie es ist mit den üblichen x86-C Aufrufkonventionen. Dies ist, weil die ersten paar Argumente übergeben werden, die über Register.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ändern
zu
und es sollte funktionieren ohne den cast.
Erstens, die Vorbild für Ihre dVsprintf ist falsch.
arglist klar hat der Typ
va_list
aus dem Kontext.Zweitens, warum nicht einfach
vsnprintf
stattdVsprintf
?Drittens, Ihre Funktion drawCenteredString klar unendlich eine Rekursion, das ist nicht gut:
__va_list_tag*
muss der zugrunde liegende Typ va_list. Dies ist schwer zu überprüfen, da va_list ist die gcc-Implementierung abhängig, und ist nicht definiert in der system-header-Dateien, soweit ich das sehen kann.Sollte dies funktionieren:
__va_list_tag*
ist die versteckte Art der Ausführung der...
, das ist, warum es nicht wie diechar*
typecast-plötzlich der Zeiger war kein 32 bit mehr...Wenn man bedenkt das ist C++, haben Sie mehr als ein C++ - Ansatz als va_args? Mehrere Ideen in den Sinn kommen:
<<
Betreiber zu tun, die dannIn meinem Fall die Umbenennung der stdarg.h in...osprey/obj/einbeziehen, um fix_starg.h, soved der Ausstellung,und natürlich der header, die benötigt stdarg.h auch muss bearbeitet werden: #include . Offenbar stdarg.h sitzen aus...kernel/obj/include war die Schaffung eines Konflikts in bionic. Ich habe bemerkt, dass dieses Problem mit ein paar header-Dateien (particuarily Arten.h und ähnliche Variationen). Die Header scheinen in Ordnung zu sein, die in kernel/include und in bionic sobald aber die sind im kernel/obj/incudes oder kernel/obj/includes/linux, es scheint sich um ein Problem zu schaffen. Ich denke, dieser Ordner wird anders verarbeitet, zumindest schien es zu erstellen Chaos in der Bionik. Umbenennen der header-Dateien, die schien, um das Problem zu lösen.