Sdílet prostřednictvím


Ladění optimalizovaného kódu

Tento článek vysvětluje, jaké přepínače kompilátoru nastavit, abyste mohli lépe ladit optimalizovaný kód.

Lepší prostředí je k dispozici od sady Visual Studio 2022 verze 17.14, která umožňuje ladit optimalizovaný kód, jako by byl zkompilován neoptimalizovaný, a přitom zachovat rychlost optimalizovaného kódu. Další informace naleznete v tématu dynamické ladění C++ (Preview).

Poznámka:

Dialogová okna a příkazy nabídek, která vidíte, se mohou lišit od těch, které jsou popsány v nápovědě, v závislosti na vašem aktivním nastavení nebo edici. Pokud chcete změnit nastavení, zvolte Nastavení importu a exportu v nabídce Nástroje. Další informace naleznete v tématu Obnovit všechna nastavení.

Poznámka:

Možnost kompilátoru /Zo (Enhance Optimized Debugging, vylepšit optimalizované ladění) (představená v sadě Visual Studio Update 3) generuje podrobnější informace o ladění pro optimalizovaný kód (projekty, které nejsou sestaveny pomocí možnosti kompilátoru /Od). Viz /O Možnosti (optimalizace kódu)). To zahrnuje vylepšenou podporu pro ladění lokálních proměnných a vložených funkcí.

Možnost Upravit a pokračovat je zakázána při použití možnosti kompilátoru /Zo .

Když kompilátor optimalizuje kód, přemísťuje a reorganizuje pokyny. Výsledkem je efektivnější kompilovaný kód. Kvůli tomuto uspořádání debugger ne vždy může identifikovat zdrojový kód, který odpovídá sadě instrukcí.

Optimalizace může ovlivnit:

  • Optimalizátor může odebrat místní proměnné nebo je přesunout do umístění, kterým ladicí program nerozumí.

  • Pozice uvnitř funkce, které se změní, když optimalizátor slučuje bloky kódu.

  • Názvy funkcí pro rámce v zásobníku volání, což může být chybné, pokud optimalizátor sloučí dvě funkce.

    Rámce, které vidíte v zásobníku volání, jsou téměř vždy správné, za předpokladu, že máte symboly pro všechny rámce. Rámce v zásobníku volání budou chybné, pokud máte poškození zásobníku, pokud máte funkce napsané v jazyce sestavení nebo pokud existují rámce operačního systému bez odpovídajících symbolů v zásobníku volání.

    Globální a statické proměnné se vždy zobrazují správně. Platí to i pro rozvržení struktury. Pokud máte ukazatel na strukturu a hodnota ukazatele je správná, zobrazí se správná hodnota každé členské proměnné struktury.

    Vzhledem k těmto omezením byste měli ladit pomocí neoptimalizované verze programu, pokud je to vůbec možné. Ve výchozím nastavení je optimalizace vypnutá v konfiguraci ladění programu C++ a je zapnutá v konfiguraci vydané verze.

    Chyba se ale může objevit pouze v optimalizované verzi programu. V takovém případě je nutné ladit optimalizovaný kód.

Zapnutí optimalizace v konfiguraci sestavení pro ladění

  1. Při vytváření nového projektu vyberte Win32 Debug cíl. Použijte cíl Win32 Debug dokud nebude program plně laděný a jste připraveni vytvořit cíl Win32 Release. Kompilátor neoptimalizuje Win32 Debug target.

  2. Vyberte projekt v Průzkumníku řešení.

  3. V nabídce Zobrazit klikněte na Stránky vlastností.

  4. V dialogovém okně Stránky vlastností se ujistěte, že Debug je vybrána v rozevíracím seznamu Konfigurace .

  5. V zobrazení složek vlevo vyberte složku C/C++ .

  6. Ve složce C++ vyberte Optimization.

  7. V seznamu vlastností napravo najděte Optimization. Nastavení vedle něj pravděpodobně říká Disabled (/Od). Zvolte jednu z dalších možností (Minimum Size``(/O1), Maximum Speed``(/O2), Full Optimization``(/Ox) nebo Custom).

  8. Pokud jste zvolili Custom možnost Optimization, můžete nyní nastavit možnosti pro kteroukoli z dalších vlastností zobrazených v seznamu vlastností.

  9. Vyberte vlastnosti konfigurace, C/C++, uzel příkazového řádku na stránce vlastností projektu a přidejte (/Zo) do textového pole Další možnosti .

    Výstraha

    Přidání /Zo zakáže úpravy a pokračování.

    Při ladění optimalizovaného kódu použijte okno Disassembly, abyste zjistili, jaké pokyny se vytvoří a spustí. Když nastavíte zarážky, musíte vědět, že se zarážka může pohybovat společně s pokyny. Představte si například následující kód:

for (x=0; x<10; x++)

Předpokládejme, že jste na tomto řádku nastavili bod přerušení. Možná očekáváte, že se zarážka zachytí 10krát, ale pokud je kód optimalizovaný, zarážka se zachytí pouze jednou. Je to proto, že první instrukce nastaví hodnotu x na 0. Kompilátor rozpozná, že tuto operaci stačí provést jen jednou, a přesune ji mimo smyčku. Zarážka se s ní přesune. Pokyny, které porovnávají a inkrementují x, zůstanou uvnitř smyčky. Při zobrazení okna disassemblace je jednotka kroku automaticky nastavena na instrukce pro větší kontrolu, což je užitečné při procházení optimalizovaného kódu.