2016-07-21 15 views
1

Ich habe schon seit geraumer Zeit die folgende Funktion wurde unter Verwendung von:Variadische Funktion arbeitet in Win32 aber nicht in Win64

void AddRow(int iNumOfColumns,...) 
{ 
    int* pValuePerColumn = (int*)&iNumOfColumns+1; 

    for (int i=0; i<iNumOfColumns; i++) 
    { 
     // Do something with pValuePerColumn[i] 
    } 
} 

Jetzt stellt sich heraus, dass es auf Win64 für einen unserer Kunden abstürzt.

Ich habe keine 64-Bit-Plattform zur Hand, aber ich gehe davon aus, dass der Grund ist:

Wenn die Funktion aufgerufen wird, werden die Argumente in den Stapel als 64-Bit-Werte geschoben.

Unter dieser Annahme glaube ich, dass das Problem durch das Ersetzen von int* durch size_t* behoben werden kann.


Meine Fragen sind:

  • Ist meine Analyse richtig?
  • Ist meine Lösung richtig?
  • Gibt es einen "konventionellen" Weg, dies zu lösen?
+3

Sie mit stdarg.h vertraut sind? – 2501

+1

@ 2501: Ja, ich nehme an, dass du die Verwendung von 'va_list' und' va_args' implizierst? –

+0

Sie sollten va_args für die Portabilität verwenden. Weitere Informationen finden Sie unter [Microsoft x86-Aufrufkonvention] (https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention). Wenn Sie stdarg.h verwenden, kümmert sich Ihr Compiler darum. –

Antwort

5

einen Zeiger auf einen hinter dem letzten Element des Arrays Derefencing, oder ein nicht-Array-Objekt ist undefinierten Verhalten:

int* pValuePerColumn = (int*)&iNumOfColumns+1; 
... 
pValuePerColumn[i] 

den Typ size_t Wechsel ist für dieses Problem keine Rolle.

Die einzig richtige Art und Weise variable Argumente verwenden, sind Makros in stdarg.h zur Verfügung gestellt.

+0

Danke. Ein Beispiel, wie man die Argumente iteriert, würde die Antwort perfekt machen (obwohl es mir gut geht). –

+0

BTW, "Derefencing einen Zeiger auf eine nach dem letzten Element ... ist UB" - Ist das nicht, was 'stdarg.h' tut sowieso? Oder ist es ein plattformabhängiges Problem, da der Sprachstandard nicht definiert, wie Funktionsargumente in den Stapel geschoben werden (anders ausgedrückt, wird eine eindeutige Version von 'stdarg.h' zusammen mit jedem Compiler bereitgestellt)? –

+0

@barakmanos Es ist für jede Architektur anders implementiert. – 2501

3

sollten Sie varargs verwenden, um zusätzliche Parameter in tragbarer Art und Weise zuzugreifen. Suchen Sie nach va_list Dokumente. Wahrscheinlich sollte Ihr Code aussehen nächsten

void AddRow(int iNumOfColumns,...) 
{ 
    va_list ap; 

    va_start(ap, iNumOfColumns); 
    for (int i=0; i<iNumOfColumns; i++) 
    { 
     int col = va_arg(ap, int); 
     // Do something with col 
    } 

    va_end(ap); 
} 

Und wie ich auf Win64 ersten vier Integer-args erinnern werden über die Register, nicht über den Stack übergeben, so Tricks mit Zeigern wird nicht funktionieren.

+0

Wo in meiner Frage haben Sie die Verwendung von 'varargs' gesehen? –

+0

OK, danke für das Kodierungsbeispiel. Sie sollten die Eröffnungsaussage wahrscheinlich entfernen, da ich nirgendwo in meiner Frage 'varargs' erwähnt habe. –

+0

@barakmanos Es gibt "Variadic-Funktion" im Titel, nicht wahr? Und es scheint, als ob Ihr Code versucht, auf Argumente zuzugreifen, die nach 'iNumOfColumns' übergeben wurden. – Sergio

Verwandte Themen