c ++ - Skal jeg foretrække 'standard' -opkaldskonventionen over \_\_fastcall, når jeg ikke virkelig bryr mig om den kaldende konvention?

Indlæg af Hanne Mølgaard Plasc

Problem



Vi har en kæmpe C ++ kodebase med masser af COM objekter. Hver funktion, der udsættes for COM, skal have \_\_stdcall call convention (normalt STDMETHODCALLTYPE makro) og så har vi mange funktioner mærket STDMETHODCALLTYPE.


Nu ser jeg en funktion, der ikke direkte kaldes via COM, men kaldes kun fra vores C ++ kode, og denne funktion har også STDMETHODCALLTYPE makro i sin signatur. Jeg er helt sikker på at makro er ubrugelig der - ingen opkald via COM til den funktion nogensinde sker.


Skal jeg droppe \_\_stdcall, så det bliver en 'standard' opkaldskonferencefunktion? Hvordan træffer jeg sådanne beslutninger?

Bedste reference


Den eneste grund til, at COM-emnerne udtrykkeligt angiver kaldkonventionen, er, fordi den bruges over DLL-grænser.

Så min rådgivning ville være at droppe den eksplicitte indstilling af opkaldskonventionen og indstille den af ​​compilerindstillingerne.

Generelt:

Hvis funktionerne eksporteres som en DLL-sæt, er der en makro, der definerer kaldkonventionen i overskrifterne. Dette forhindrer brugere fra DLL'en til at bruge en forkert opkaldskonference, når der knyttes til din DLL. Eksplicit overstyrer compilerindstillingen.

Brug ikke nogen kaldkonvektion på lokale funktioner. Konventionen kan indstilles af en compiler switch. Hvis du beslutter dig for at angive en eksplicit, skal du gøre det på alle funktioner. Så har du stadig et centralt sted at ændre kaldkonventionen.

Selvfølgelig, hvis det giver mening, eller du har brug for nogle specielle kaldkonventioner, f.eks. Fastcall for optimering, skal du også angive eksplicit.

Andre referencer 1


Min tilgang er at bruge standardkompileropkaldskonventionen til intern kode og at anvende en veldefineret udtrykkeligt angivet kaldkonvention for alle metoder, der eksporteres over en modulgrænse.


Standardopkaldskonventionen for de fleste kompilatorer gør god brug af registre for præstationsårsager, så der er fordele ved at bruge det, hvis det er relevant. Det gør også din kode lettere på øjet, da du ikke behøver at angive konventionen for at få standard.


For eksporterede funktioner skal du tydeligt angive konventionen. Hvis du laver et bibliotek, som du forventer, bliver kaldt fra andre sprog end C eller C + +, ville det være konventionelt at bruge stdcall. Hvis du kun forventer C eller C + + klienter, så er cdecl nok den mest almindelige konvention.

Andre referencer 2


Når Windows skiftede fra \_\_ cdecl til \_ \_stdcall som standardopkaldskonventionen, faldt produktets størrelse med ca. 10\%. At besparelserne var helt relateret til at fjerne stakjusteringer efter at have kaldt stdcall-metoderne (\_\_cdecl er en 'opkalder justerer stakken for at fjerne parametre', kaldes konventionen, \_\_stdcall er en 'callee justerer stakken til at fjerne parametre' kaldkonventionen, da der er flere kaldere end callees, skifte reducerer størrelsen af ​​dine binære filer).


Ulempen ved at bruge \_\_stdcall er at du ikke har variable #s af argumenter (da callee justerer stakken, kan de ikke vide, hvor mange parametre den opkalder har angivet).


Nederste linje: Skift til \_\_stdcall fra 'standard' opkaldskonventionen kan resultere i en reduktion i størrelsen af ​​din binære. Det kan eller ikke være vigtigt for dig.


Men som nævnt ovenfor, hvis din kode er EVER , der er tilgængelig i en anden compiland (f.eks. Hvis du leverer en .lib-fil til en anden), er det absolut vigtigt, at du erklærer den anvendte kaldkonvention.

Andre referencer 3


Har du hele programoptimering og link-time-kodegenerering aktiveret? Hvis det er tilfældet, og du ikke eksporterer funktionen fra din DLL eller videregiver henvisninger til det, kan kompilatoren generere brugerdefinerede kaldkonventioner til den funktion eller inline den (selvom den ikke er defineret i en headerfil). [[[6] [7]

Andre referencer 4


Du kan se igennem dine kort for at se, om det refereres, ved at søge i ODL-filer, der er forbundet med løsningen. Hvis det ikke er der, har det ikke en grænseflade, og du kan ændre opkaldskonventionen. Der er risiko for, at en anden antager, at alle funktioner er oprettet med denne indkaldelseskonvention, og de kunne tilføje en grænseflade på et senere tidspunkt.