Is het mogelijk om te forceren dat een functie niet inline is?

Ik wil een kleine functie forceren om niet als inline-functie te worden gecompileerd, ook al is het heel eenvoudig. Ik denk dat dit nuttig is voor debug-doeleinden. Is er een trefwoord om dit te doen?


Antwoord 1, autoriteit 100%

In Visual Studio 2010 vertelt __declspec(noinline)de compiler om nooit een bepaalde lidfunctie inline te geven, bijvoorbeeld:

class X {
     __declspec(noinline) int member_func() {
          return 0; 
     }
};

edit: Bovendien worden bij het compileren met /clrfuncties met beveiligingsattributen nooit inline weergegeven (nogmaals, dit is specifiek voor VS 2010).

Ik denk echter niet dat het nuttig zal zijn bij het debuggen.


Antwoord 2, autoriteit 98%

__declspec(noinline)voor VC++. In tegenstelling tot de man-pagina lijkt dit te werken voor vrijstaande functies, en ik denk niet dat ik het ooit voor een lidfunctie heb gebruikt. U kunt – hoewel ik dat nooit heb gedaan – overwegen om ook met de optimalisatievlaggen te spelen, zodat alleen inline-functies worden overwogen voor inlining, hoewel dit natuurlijk een globaal effect heeft en dat kan niet zijn wat je wilt.

__attribute__((noinline))voor gcc (en een aantal minder gebruikelijke compilers die de gcc-attribuutsyntaxis ondersteunen). Ik moet toegeven, ik denk niet dat ik dit ooit echt heb gebruikt, maar het lijkt er te zijn.

(Natuurlijk komen deze twee soorten annotaties op verschillende plaatsen voor, dus het is een beetje vervelend om code te maken die voor beide aangenaam is.)

Ik weet niet zeker hoe een van deze interageert met het inlineC++ trefwoord; Ik heb ze alleen gebruikt bij het debuggen (wanneer ik gewoon wil dat een bepaalde niet-inline functie na optimalisatie niet inline blijft) of bij het onderzoeken van gegenereerde code (en ik raak in de war omdat willekeurige dingen worden inline).


Antwoord 3, autoriteit 27%

Houd er rekening mee dat inline relevant is op de function callsite, dezelfde functie kan in sommige situaties wel inline zijn en in andere niet.

Als uw functie zichtbaar is buiten de compilatie-eenheid, moet de hoofdtekst van de functie nog steeds beschikbaar zijn voor iedereen die deze later wil aanroepen, zelfs als deze is opgenomen in allevan de huidige plaatsen waar deze wordt gebruikt. (door te linken met het objectbestand).

Als u een call-site niet inline wilt hebben, kunt u een aanwijzer naar een functie gebruiken.

void (*f_ptr)(int); // pointer to function
volatile bool useMe = true; // disallow optimizations 
if (useMe)
   f_ptr = myFunc;
else
   f_ptr = useOtherFunc;
f_ptr(42); // this will not be inlined

Antwoord 4, autoriteit 10%

[[gnu::noinline]]kenmerk

We kunnen ook de C++11-attribuutspecificatiesyntaxis gebruiken met het niet-standaard gnu::noinline-kenmerk: https://en.cppreference.com/w/cpp/language/attributes

Het is slechts een kwestie van tijd totdat dat gnu::-gedeelte een toekomstige C++-standaard krijgt om een ​​gestandaardiseerde [[noinline]]🙂

main.cpp

[[gnu::noinline]]
int my_func() {
    return 1;
}
int main() {
    return my_func();
}

Compileren en demonteren:

g++ -ggdb3 -O3 -o main.out -std=c++11 -Wall -Wextra -pedantic-errors main.cpp
gdb -batch -ex 'disassemble/r main' main.out

Met [[gnu::noinline]]:

  0x0000000000001040 <+0>:     f3 0f 1e fa     endbr64 
   0x0000000000001044 <+4>:     e9 f7 00 00 00  jmpq   0x1140 <my_func()>

Zonder [[gnu::noinline]]:

  0x0000000000001040 <+0>:     f3 0f 1e fa     endbr64 
   0x0000000000001044 <+4>:     b8 01 00 00 00  mov    $0x1,%eax
   0x0000000000001049 <+9>:     c3      retq

Getest op Ubuntu 19.10.


Antwoord 5, autoriteit 8%

Eenvoudig: laat de compiler de definitie van de functie niet zien. Dan kan het onmogelijk inline zijn. Dat werkt natuurlijk alleen als het uwcode is.

Als het gaat om het debuggen van code van derden… ja, dit zou handig zijn, vooral als je code van derden van een afstand zou kunnen zappen. Iedereen die foutopsporing heeft uitgevoerd in code die veel shared_ptr dereferenties bevat, weet waar ik het over heb.


Antwoord 6, autoriteit 2%

Veel compilers kunnen cross-translation-unit inlining uitvoeren. Visual Studio heeft het al vijf jaar en ik geloof dat GCC het nu kan doen – vooral sinds de OP getagd als Visual C++, is het een goede gok dat zijn compiler het aankan.

De eenvoudigste manier om dit te doen is door het adres van de functie te nemen en er dan iets niet-betekenends mee te doen, zoals het aanroepen of doorgeven aan een besturingssysteem/externe bibliotheekfunctie. De compiler kan dat soort functies niet inline maken.

Waarom zou je dat ooit willen, IDK.

@comments:

Als de OP srsly, srsly dit nodig heeft, dan kan hij het compileren als een lib en er statisch naar linken.


Antwoord 7, autoriteit 2%

Als het een lidfunctie van een klasse is, maak deze dan virtueel.


Antwoord 8

U kunt de klasse-implementatie verdelen tussen een header- en cpp-bestand. als je de functie buiten de klassedefinitie plaatst, zal je kleine functie niet inline zijn.


Antwoord 9

Is het mogelijk om te forceren dat een functie niet inline is?

Ik zal niet eens proberen die vraag te beantwoorden, omdat het niet relevant is om me hier druk over te maken, behalve om de twee redenen die hieronder worden uiteengezet.

Inlinen is eigenlijk

  1. een optimalisatie die voor u grotendeels transparant is
  2. een manier om functies in headers te laten definiëren zonder meerdere definitiefouten te krijgen

(Sommigen zouden de volgorde van deze twee veranderen, maar ik blijf bij de traditionele volgorde.)

Tenzij een van beide A)je absoluut moet definieereen functie in een header of B)u profileert en optimaliseert een stuk code en weet beter dan de compiler wat moet worden inline en wat niet, inlining zou voor u geen probleem moeten zijn.
Het zou zeker geen probleem moeten zijn vanwege debuggen. Je debugger moet (en in het geval van VC ook) dat voor je regelen.

Other episodes