다음을 통해 공유


C++ 동적 디버깅(미리 보기)

중요합니다

C++ 동적 디버깅은 현재 미리 보기로 제공됩니다. 이 정보는 릴리스 전에 크게 수정될 수 있는 시험판 기능과 관련이 있습니다. Microsoft는 여기에 제공된 정보와 관련하여 명시적이거나 묵시적인 보증을 하지 않습니다.

Visual Studio 2022 버전 17.14 미리 보기 2부터 사용할 수 있는 이 미리 보기 기능은 x64 프로젝트에만 적용됩니다.

C++ 동적 디버깅을 사용하면 최적화된 코드가 최적화되지 않은 것처럼 디버그할 수 있습니다. 이 기능은 프레임 속도가 높은 게임 개발자와 같이 최적화된 코드의 성능 이점이 필요한 개발자에게 유용합니다. C++ 동적 디버깅을 사용하면 최적화된 빌드의 성능 이점을 희생하지 않고도 최적화되지 않은 코드의 디버깅 환경을 즐길 수 있습니다.

최적화된 코드를 디버깅하면 문제가 발생합니다. 컴파일러는 코드를 최적화하기 위해 지침을 재배치하고 재구성합니다. 결과는 더 효율적인 코드이지만 다음을 의미합니다.

  • 최적화 프로그램은 지역 변수를 제거하거나 디버거에 알 수 없는 위치로 이동할 수 있습니다.
  • 최적화 프로그램이 코드 블록을 병합할 때 함수 내의 코드는 더 이상 소스 코드와 정렬되지 않을 수 있습니다.
  • 최적화 프로그램에서 두 함수를 병합하는 경우 호출 스택의 함수에 대한 함수 이름이 잘못되었을 수 있습니다.

과거에 개발자는 최적화된 코드를 디버깅하는 과정에서 이러한 문제 및 기타 문제를 처리했습니다. 이제 C++ 동적 디버깅을 사용하면 최적화된 코드를 최적화되지 않은 것처럼 한 단계씩 실행할 수 있으므로 이러한 문제가 제거되었습니다.

최적화된 이진 파일을 생성하는 것 외에도, /dynamicdeopt를 사용하여 컴파일하면 디버깅 중에 활용되는 최적화되지 않은 이진 파일도 생성됩니다. 중단점을 추가하거나 함수(__forceinline 함수 포함) 안으로 들어갈 때, 디버거는 최적화되지 않은 바이너리를 로드합니다. 그런 다음 최적화된 코드 대신 함수에 대해 최적화되지 않은 코드를 디버그할 수 있습니다. 최적화되지 않은 코드를 디버깅하는 것처럼 디버그할 수 있지만 나머지 프로그램에서 최적화된 코드의 성능 이점을 얻을 수 있습니다.

C++ 동적 디버깅 사용해 보기

먼저 최적화된 코드를 디버그하는 것이 어떤 것인지 검토해 보겠습니다. 그런 다음 C++ 동적 디버깅이 프로세스를 간소화하는 방법을 확인할 수 있습니다.

  1. Visual Studio에서 새 C++ 콘솔 애플리케이션 프로젝트를 만듭니다. ConsoleApplication.cpp 파일의 내용을 다음 코드로 바꿉니다.

    // Code generated by GitHub Copilot
    #include <iostream>
    #include <chrono>
    #include <thread>
    
    using namespace std;
    
    int step = 0;
    const int rows = 20;
    const int cols = 40;
    
    void printGrid(int grid[rows][cols])
    {
        cout << "Step: " << step << endl;
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                cout << (grid[i][j] ? '*' : ' ');
            }
            cout << endl;
        }
    }
    
    int countNeighbors(int grid[rows][cols], int x, int y)
    {
        int count = 0;
        for (int i = -1; i <= 1; ++i)
        {
            for (int j = -1; j <= 1; ++j)
            {
                if (i == 0 && j == 0)
                {
                    continue;
                }
    
                int ni = x + i;
                int nj = y + j;
                if (ni >= 0 && ni < rows && nj >= 0 && nj < cols)
                {
                    count += grid[ni][nj];
                }
            }
        }
        return count;
    }
    
    void updateGrid(int grid[rows][cols])
    {
        int newGrid[rows][cols] = { 0 };
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                int neighbors = countNeighbors(grid, i, j);
                if (grid[i][j] == 1)
                {
                    newGrid[i][j] = (neighbors < 2 || neighbors > 3) ? 0 : 1;
                }
                else
                {
                    newGrid[i][j] = (neighbors == 3) ? 1 : 0;
                }
            }
        }
        // Copy newGrid back to grid
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                grid[i][j] = newGrid[i][j];
            }
        }
    }
    
    int main()
    {
        int grid[rows][cols] = { 0 };
    
        // Initial configuration (a simple glider)
        grid[1][2] = 1;
        grid[2][3] = 1;
        grid[3][1] = 1;
        grid[3][2] = 1;
        grid[3][3] = 1;
    
        while (true)
        {
            printGrid(grid);
            updateGrid(grid);
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            cout << "\033[H\033[J"; // Clear the screen
            step++;
        }
    
        return 0;
    }
    
  2. 솔루션 구성 드롭다운 목록을 릴리스로 변경합니다. 솔루션 플랫폼 드롭다운 목록이 x64로 설정되어 있는지 확인합니다.

  3. 빌드>솔루션 다시 빌드를 선택하여 다시 만듭니다.

  4. 줄 55 int neighbors = countNeighbors(grid, i, j);updateGrid()의 중단점을 설정합니다. 프로그램을 실행합니다.

  5. 중단점에 도달하면 지역 변수 창을 봅니다. 주 메뉴에서Windows> 로컬 디버그> 선택합니다. i 또는 j의 값을 지역 창에서 볼 수 없습니다. 컴파일러가 그것들을 최적화하여 제거했습니다.

  6. 줄 19 cout << (grid[i][j] ? '*' : ' ');printGrid()에 중단점을 설정해보세요. 할 수 없습니다. 컴파일러가 코드를 최적화했기 때문에 이 동작이 필요합니다.

프로그램을 중지하고 C++ 동적 디버깅을 사용하도록 설정하고 다시 시도합니다.

  1. 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택하여 프로젝트 속성 페이지를 엽니다.

  2. 고급>C++ 동적 디버깅을 선택하고 설정을 로 변경합니다.

    고급 프로젝트 속성을 보여 주는 스크린샷

    구성 속성 > 고급 > C++ 동적 디버깅을 사용하도록 속성 페이지가 열립니다. 속성이 Yes로 설정됩니다.

    이 단계에서는 /dynamicdeopt 컴파일러 및 링커에 스위치를 추가합니다. 보이지 않는 곳에서 또한 C++ 최적화 스위치 /GL/OPT:ICF을 해제합니다. 이 설정은 명령줄에 수동으로 추가한 스위치 또는 설정된 다른 최적화 스위치(예: /O1.)를 덮어쓰지 않습니다.

  3. 빌드>솔루션 다시 빌드를 선택하여 다시 만듭니다. 동적 디버깅 및 전체 프로그램 최적화가 호환되지 않음을 나타내는 빌드 진단 코드 MSB8088 가 나타납니다. 이 오류는 컴파일 중에 전체 프로그램 최적화(/GL)가 자동으로 꺼졌다는 것을 의미합니다.

    프로젝트 속성에서 전체 프로그램 최적화를 수동으로 끌 수 있습니다. 구성 속성>고급>전체 프로그램 최적화를 선택하고 설정을 기로 변경합니다. 이제 MSB8088 경고로 처리되지만 이후 버전의 Visual Studio에서 오류로 처리될 수 있습니다.

  4. 앱을 다시 실행합니다.

    이제 줄 55에서 중단점에 도달하면, i 창에서 j의 값을 볼 수 있습니다. 호출 스택 창은 updateGrid()이 최적화 해제되었고, 파일 이름은 life.alt.exe입니다. 이 대체 이진 파일은 최적화된 코드를 디버그하는 데 사용됩니다.

    updateGrid 함수 디버깅을 보여 주는 스크린샷.

    중단점이 updateGrid 함수에 표시됩니다. 호출 스택은 함수가 최적화되지 않았으며 파일 이름이 life.alt.exe. 로컬 창에는 i 및 j의 값과 함수의 다른 지역 변수가 표시됩니다.

    함수에 updateGrid() 중단점을 설정했기 때문에 요청 시 함수의 최적이 해제됩니다. 디버깅하는 동안 최적화된 함수를 실행을 넘어가면 최적화가 취소되지 않습니다. 함수 안으로 진입하면 최적화가 해제됩니다. 함수를 비최적화하는 주요 방법은 함수에 중단점을 설정하거나 한 단계씩 들어가는 것입니다.

    호출 스택 창에서 함수를 비활성화할 수도 있습니다. 함수 또는 선택한 함수 그룹을 마우스 오른쪽 단추로 클릭하고 다음 항목에서 Deoptimize를 선택합니다. 이 기능은 호출 스택의 다른 위치에서 중단점을 설정하지 않은 최적화된 함수에서 지역 변수를 보려는 경우에 유용합니다. 이와 같이 최적화 해제된 함수는 중단점 창에서 최적화 해제된 함수라는 중단점 그룹으로 함께 그룹화됩니다. 중단점 그룹을 삭제하면 연결된 함수가 최적화된 상태로 되돌아갑니다.

조건부 및 종속 중단점 사용

  1. 줄 19 cout << (grid[i][j] ? '*' : ' ');printGrid()에서 중단점을 다시 설정해 보세요. 이제 작동합니다. 함수에 중단점을 설정하면 함수가 최적화되지 않아 일반적으로 디버그할 수 있게 됩니다.

  2. 줄 19에서 중단점을 마우스 오른쪽 단추로 클릭하고 조건을 선택한 다음 조건을 으로 i == 10 && j== 10설정합니다. 그런 다음 다음의 중단점이 적중될 때만 사용 확인란을 선택합니다. 드롭다운 목록에서 줄 55의 중단점을 선택합니다. 이제 줄 19의 중단점은 줄 50의 중단점이 먼저 적중된 후, grid[10][10]이 콘솔에 출력을 시도할 때까지 적중되지 않습니다.

    요점은 최적화된 함수에서 조건부 및 종속 중단점을 설정하고 최적화된 빌드에서 디버거에서 사용할 수 없는 로컬 변수 및 코드 줄을 사용할 수 있다는 것입니다.

    줄 19의 조건부 중단점 설정을 보여 주는 스크린샷

    조건부 브레이크포인트가 19번째 줄에 표시되어 있습니다, cout < < (grid[i][j] ? '*' : ' ');. 조건은 i == 10 && j== 10으로 설정됩니다. 다음 중단점이 적중된 경우에만 사용할 수 있는 확인란이 선택되어 있습니다. 중단점 드롭다운 목록은 life.cpp 줄 55로 설정됩니다.

  3. 앱을 계속 실행합니다. 줄 19의 중단점이 적중되면 줄 15를 마우스 오른쪽 단추로 클릭하고 다음 문 설정을 선택하여 루프를 다시 실행할 수 있습니다.

    printGrid 함수 디버깅을 보여 주는 스크린샷

    조건문과 종속된 중단점이 19번째 줄에 도달했습니다. 코드: cout < <(grid[i][j] ? '*' : ' ');. 로컬 창에는 i 및 j의 값과 함수의 다른 지역 변수가 표시됩니다. 호출 스택 창에는 함수가 최적화되지 않았으며 파일 이름이 life.alt.exe.

  4. 최적화되지 않은 함수를 최적화된 상태로 되돌리려면 모든 중단점을 삭제합니다. Visual Studio 주 메뉴에서모든 중단점 삭제>를 선택합니다. 그러면 모든 함수가 최적화된 상태로 돌아갑니다.

    이 연습에서는 수행하지 않은 다음 항목 옵션에서 호출 스택Deoptimize 를 통해 중단점을 추가하는 경우, 최적화되지 않은 함수 그룹을 마우스 오른쪽 단추로 클릭하고 삭제 를 선택하여 해당 그룹의 함수만 최적화된 상태로 되돌릴 수 있습니다.

    중단점 창을 보여 주는 스크린샷.

    중단점 창에는 비최적화된 함수 그룹이 표시됩니다. 그룹이 선택되고 중단점 그룹 삭제가 선택된 상황에 맞는 메뉴가 열립니다.

C++ 동적 디버깅 끄기

최적화된 코드를 디옵티마이저 없이 디버그하거나, 최적화된 코드에 중단점을 설정해도 중단점이 작동될 때 코드가 최적화된 상태를 유지할 필요가 있을 수 있습니다. 여러 가지 방법으로 동적 디버깅을 해제하거나 중단점에 도달할 때 코드의 작동을 중단하지 않도록 할 수 있습니다.

  • Visual Studio 주 메뉴에서 도구>옵션>디버깅 일반을> 선택합니다. 가능한 경우 디버그된 함수를 자동으로 디버그 해제(.NET 8+, C++ 동적 디버깅) 확인란의 선택을 취소합니다. 다음에 디버거가 시작될 때 코드는 최적화된 상태로 유지됩니다.
  • 많은 동적 디버깅 중단점은 최적화된 이진 파일과 최적화되지 않은 이진 파일에 있는 중단점의 두 가지 중단점입니다. 중단점 창에서 열 표시>함수를 선택합니다. 이진 파일과 연결된 중단점을 제거하십시오 alt. 쌍의 다른 중단점은 최적화된 코드에서 중단됩니다.
  • 디버깅할 때 Visual Studio 주 메뉴에서Windows>디스어셈블리>를 선택합니다. 포커스가 있는지 확인합니다. 디스어셈블리 창을 통해 함수에 들어가면 함수는 비최적화되지 않습니다.
  • /dynamicdeoptcl.exe, lib.exe, link.exe에 전달하지 않음으로써 동적 디버깅을 완전히 비활성화합니다. 타사 라이브러리를 사용하고 다시 빌드할 수 없는 경우, 최종 /dynamicdeopt 단계에서 해당 이진 파일에 대한 동적 디버깅을 비활성화하기 위해 link.exe를 전달하지 마세요.
  • 단일 바이너리에 대해 동적 디버깅을 신속하게 비활성화하려면(예: test.dll), alt 바이너리의 이름을 바꾸거나 삭제하십시오(예: test.alt.dll).
  • 하나 이상의 .cpp 파일에 대해 동적 디버깅을 사용하지 않도록 설정하려면 파일을 빌드할 때 전달 /dynamicdeopt 하지 마세요. 프로젝트의 나머지 부분에서는 동적 디버깅을 사용하여 빌드됩니다.

Unreal Engine에서 C++ 동적 디버깅 사용

Unreal Engine 5.6은 Unreal Build Tool과 Unreal Build Accelerator 모두에 대해 C++ 동적 디버깅을 지원합니다. 두 가지 방법으로 사용하도록 설정할 수 있습니다.

  • 프로젝트의 Target.cs 파일을 WindowsPlatform.bDynamicDebugging = true을 포함하도록 수정합니다.

  • 개발 편집기 구성을 사용하고 다음을 포함하도록 수정 BuildConfiguration.xml 합니다.

    <WindowsPlatform>
        <bDynamicDebugging>true</bDynamicDebugging>
    </WindowsPlatform>
    

Unreal Engine 버전 5.5 이하의 경우, GitHub에서 Unreal Build Tool의 변경 사항을 선택하여 당신의 리포지토리에 적용하세요. 그런 다음, 위에 표시된 대로 사용하도록 설정합니다 bDynamicDebugging . 또한 Unreal Engine 5.6에서 Unreal Build Accelerator를 사용해야 합니다. ue5-main의 최신 비트를 사용하거나 다음 BuildConfiguration.xml을 추가하여 UBA를 사용하지 않도록 설정합니다.

<BuildConfiguration>
    <bAllowUBAExecutor>false</bAllowUBAExecutor>
    <bAllowUBALocalExecutor>false</bAllowUBALocalExecutor>
</BuildConfiguration>

Unreal Engine을 빌드하는 방법을 구성하는 방법에 대한 자세한 내용은 빌드 구성을 참조하세요.

문제 해결

중단점이 최적 해제 함수에 적중되지 않는 경우:

  • [Deoptimized] 프레임에서 나오면, 호출자가 중단점 때문에 비최적화되었거나, 현재 함수로 가는 도중 호출자에 들어갔다면, 최적화된 코드에 있을 수 있습니다.

  • alt.exealt.pdb 파일이 빌드되었는지 확인합니다. For test.exetest.pdb, test.alt.exetest.alt.pdb 동일한 디렉터리에 있어야 합니다. 이 문서에 따라 올바른 빌드 스위치가 설정되어 있는지 확인합니다.

  • debug directory 항목이 test.exe에 존재하며, 이는 디버거가 Deoptimized 디버깅에 사용할 alt 이진 파일을 찾는 데 사용됩니다. x64 네이티브 Visual Studio 명령 프롬프트를 열고 link /dump /headers <your executable.exe>를 실행하여 deopt 항목이 있는지 확인합니다. 예제의 마지막 줄에 표시된 것처럼 deopt 열에 Type 항목이 나타납니다.

      Debug Directories
    
            Time Type        Size      RVA  Pointer
        -------- ------- -------- -------- --------
        67CF0DA2 cv            30 00076330    75330    Format: RSDS, {7290497A-E223-4DF6-9D61-2D7F2C9F54A0}, 58, D:\work\shadow\test.pdb
        67CF0DA2 feat          14 00076360    75360    Counts: Pre-VC++ 11.00=0, C/C++=205, /GS=205, /sdl=0, guardN=204
        67CF0DA2 coffgrp      36C 00076374    75374
        67CF0DA2 deopt         22 00076708    75708    Timestamp: 0x67cf0da2, size: 532480, name: test.alt.exe
    

    deopt 디버그 디렉터리 항목이 없으면 /dynamicdeopt, cl.exe, lib.exelink.exe에 전달하고 있는지 확인합니다.

  • 동적 Deoptimization은 /dynamicdeopt, cl.exe, 그리고 모든 이진 파일에 대해 lib.exelink.exe, .cpp, .lib에 전달되지 않으면 일관되게 작동하지 않을 수 있습니다. 프로젝트를 빌드할 때 적절한 스위치가 설정되는지 확인합니다.

알려진 문제에 대한 자세한 내용은 C++ 동적 디버깅: 최적화된 빌드에 대한 전체 디버깅 기능을 참조하세요.

예상대로 작동하지 않는 경우 개발자 커뮤니티에서 티켓을 엽니다. 문제에 대해 가능한 한 많은 정보를 포함합니다.

일반 사항

IncrediBuild 10.24는 C++ 동적 디버깅 빌드를 지원합니다.
FastBuild v1.15는 C++ 동적 디버깅 빌드를 지원합니다.

인라인된 함수는 요청 시 최적이 해제됩니다. 인라인 함수에 중단점을 설정하는 경우 디버거는 함수와 해당 호출자를 디옵티미징합니다. 중단점은 프로그램이 컴파일러 최적화 없이 빌드된 것처럼 예상할 수 있는 위치에 도달합니다.

함수 내에서 중단점을 비활성화해도 함수는 여전히 최적화되지 않습니다. 함수가 최적화된 상태로 되돌리려면 중단점을 제거해야 합니다.

많은 동적 디버깅 중단점은 최적화된 이진 파일과 최적화되지 않은 이진 파일에 있는 중단점의 두 가지 중단점입니다. 이러한 이유로 중단점 창에 중단점이 두 개 이상 표시됩니다.

최적화 플래그 및 를 제외하고 최적화되지 않은 버전에 사용되는 컴파일러 플래그는 최적화된 버전에 사용되는 플래그와 /dynamicdeopt동일합니다. 이 동작은 매크로 정의를 위해 설정한 모든 플래그가 비최적화된 버전에서도 설정된다는 것을 의미합니다.

비최적화된 코드는 디버그 코드와 동일하지 않습니다. 최적화되지 않은 코드는 최적화된 버전과 동일한 최적화 플래그로 컴파일되므로 디버그 관련 설정에 의존하는 어설션 및 기타 코드는 포함되지 않습니다.

시스템 통합 빌드

C++ 동적 디버깅을 사용하려면 컴파일러 및 링커 플래그를 특정 방식으로 설정해야 합니다. 다음 섹션에서는 충돌하는 스위치가 없는 동적 디버깅에 대한 전용 구성을 설정하는 방법을 설명합니다.

Visual Studio 빌드 시스템을 사용하여 프로젝트를 빌드하는 경우 동적 디버깅 구성을 만드는 좋은 방법은 Configuration Manager를 사용하여 릴리스 또는 디버그 구성을 복제하고 동적 디버깅을 수용하도록 변경하는 것입니다. 다음 두 섹션에서는 절차를 설명합니다.

새 릴리스 구성 만들기

  1. Visual Studio 주 메뉴에서 빌드>구성 관리자 를 선택하여 Configuration Manager를 엽니다.

  2. 구성 드롭다운 목록을 선택한 다음 새로 만들기...<를 선택합니다>.

    Configuration Manager를 보여 주는 스크린샷.

    Configuration Manager의 프로젝트 컨텍스트에서 구성 드롭다운 목록이 열려 있고 강조 표시됩니다.

  3. 새 솔루션 구성 대화 상자가 열립니다. 이름 필드에 새 구성의 이름(예: ReleaseDD.)을 입력합니다. 복사 설정 가져오기:릴리스로 설정되어 있는지 확인합니다. 그런 다음 확인을 선택하여 새 구성을 만듭니다.

    릴리스 빌드에 대한 새 프로젝트 구성 대화 상자를 보여 주는 스크린샷

    이름 필드가 ReleaseDD로 설정됩니다. '복사 설정에서' 드롭다운 목록이 릴리스로 설정됩니다.

  4. 새 구성이 활성 솔루션 구성 드롭다운 목록에 나타납니다. 닫기를 선택합니다.

  5. 구성 드롭다운 목록이 ReleaseDD로 설정된 상태에서 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.

  6. 고급 구성 속성>에서 C++ 동적 디버깅 사용을로 설정합니다.

  7. 전체 프로그램 최적화아니요로 설정되어 있는지 확인합니다.

    고급 프로젝트 속성을 보여 주는 스크린샷

    속성 페이지가 고급 > 구성 속성에 열립니다. C++ 동적 디버깅을 사용합니다. 속성이 Yes로 설정됩니다. 전체 프로그램 최적화가 아니오로 설정되었습니다.

  8. 구성 속성>링커>최적화에서 COMDAT 접기 사용아니요(/OPT:NOICF)로 설정되어 있는지 확인합니다.

    링커 최적화 프로젝트 속성을 보여 주는 스크린샷

    속성 페이지가 '구성 속성 > 링커 > 최적화 > CMDAT 접기 활성화'로 열립니다. 속성이 아니(/OPT:NOICF)로 설정됩니다.

이 설정은 /dynamicdeopt 컴파일러 및 링커에 스위치를 추가합니다. C++ 최적화 스위치 /GL/OPT:ICF 꺼져 있으므로 이제 C++ 동적 디버깅과 함께 사용할 수 있는 최적화된 릴리스 빌드를 원할 때 새 구성에서 프로젝트를 빌드하고 실행할 수 있습니다.

정품 빌드와 함께 사용하는 다른 스위치를 이 구성에 추가하여 동적 디버깅을 사용할 때 예상되는 스위치를 항상 정확히 켜거나 끌 수 있습니다. 동적 디버깅과 함께 사용하면 안 되는 스위치에 대한 자세한 내용은 호환되지 않는 옵션을 참조하세요.

Visual Studio의 구성에 대한 자세한 내용은 구성 만들기 및 편집을 참조하세요.

새 디버그 구성 만들기

디버그 이진 파일을 사용하지만 더 빠르게 실행하려면 디버그 구성을 수정할 수 있습니다.

  1. Visual Studio 주 메뉴에서 빌드>구성 관리자 를 선택하여 Configuration Manager를 엽니다.

  2. 구성 드롭다운 목록을 선택한 다음 새로 만들기...<를 선택합니다>.

    Configuration Manager를 보여 주는 스크린샷.

    Configuration Manager의 프로젝트 컨텍스트 부분에서는 구성 드롭다운 목록이 열리고 강조 표시됩니다.

  3. 새 프로젝트 구성 대화 상자가 열립니다. 이름 필드에 DebugDD와 같은 새 구성의 이름을 입력합니다. 복사 설정을디버그로 설정했는지 확인합니다. 그런 다음 확인을 선택하여 새 구성을 만듭니다.

    디버그 빌드에 대한 '새 프로젝트 구성 대화 상자'를 보여 주는 스크린샷

    이름 필드가 DebugDD로 설정됩니다. 복사 설정: 드롭다운 목록이 디버그로 설정됩니다.

  4. 새 구성이 활성 솔루션 구성 드롭다운 목록에 나타납니다. 닫기를 선택합니다.

  5. 구성 드롭다운 목록이 DebugDD로 설정된 상태에서 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.

  6. 구성 속성>C/C++>최적화에서 원하는 최적화를 켭니다. 예를 들어 최적화속도 최대화(/O2)로 설정할 수 있습니다.

  7. C/C++>코드 생성에서 기본 런타임 검사를기본값으로 설정합니다.

  8. C/C++>일반에서 내 코드만 디버깅 지원을 사용하지 않도록 설정합니다.

  9. 디버그 정보 형식Program Database(/Zi)로 설정합니다.

디버그 빌드와 함께 사용하는 다른 스위치를 이 구성에 추가하여 동적 디버깅을 사용할 때 예상되는 스위치를 항상 정확히 켜거나 끌 수 있습니다. 동적 디버깅과 함께 사용하면 안 되는 스위치에 대한 자세한 내용은 호환되지 않는 옵션을 참조하세요.

Visual Studio의 구성에 대한 자세한 내용은 구성 만들기 및 편집을 참조하세요.

사용자 지정 빌드 시스템 고려 사항

사용자 지정 빌드 시스템이 있는 경우 다음을 확인합니다.

  • /dynamicdeopt, cl.exe, lib.exe, 및 link.exe에 전달.
  • /ZI를 사용하지 말고, /RTC 플래그 또는 /JMC를 사용하지 마세요.

빌드 배포자를 위한:

  • 이름이 test인 프로젝트의 경우, 컴파일러는 test.alt.obj, test.alt.exp, test.obj, 및 test.exp를 생성합니다. 링커는 test.alt.exe, test.alt.pdb, test.exe, 및 test.pdb를 생성합니다.
  • 새 도구 집합 이진 파일 c2dd.dllc2.dll와 함께 배포해야 합니다.

호환되지 않는 옵션

일부 컴파일러 및 링커 옵션은 C++ 동적 디버깅과 호환되지 않습니다. Visual Studio 프로젝트 설정을 사용하여 C++ 동적 디버깅을 켜면 추가 명령줄 옵션 설정에서 특별히 설정하지 않으면 호환되지 않는 옵션이 자동으로 꺼집니다.

다음 컴파일러 옵션은 C++ 동적 디버깅과 호환되지 않습니다.

/GH
/GL
/Gh
/RTC1 
/RTCc 
/RTCs 
/RTCu 
/ZI (/Zi is OK)
/ZW 
/clr 
/clr:initialAppDomain
/clr:netcore
/clr:newSyntax
/clr:noAssembly
/clr:pure
/clr:safe
/fastcap
/fsanitize=address
/fsanitize=kernel-address

다음 링커 옵션은 C++ 동적 디버깅과 호환되지 않습니다.

/DEBUG:FASTLINK
/INCREMENTAL
/OPT:ICF  You can specify /OPT:ICF but the debugging experience may be poor

참고하십시오

/dynamicdeopt 컴파일러 플래그(미리 보기)
/DYNAMICDEOPT 링커 플래그(미리 보기)
C++ 동적 디버깅: 최적화된 빌드에 대한 전체 디버깅 기능
최적화된 코드 디버그