_DEBUG vs NDEBUG


142

코드의 디버그 섹션을 지정하기 위해 어떤 전 처리기 정의를 사용해야합니까?

#ifdef _DEBUG또는 사용 #ifndef NDEBUG하는 것이 더 좋은 방법이 #define MY_DEBUG있습니까?

_DEBUGVisual Studio와 관련이 있다고 생각합니다. NDEBUG가 표준입니까?

답변:


113

Visual Studio는 또는 옵션 _DEBUG을 지정할 때 정의 하고 표준 C 어설 션을 비활성화합니다. 적절한 경우, 즉 디버깅 코드가 MS CRT 디버깅 기술 과 일관성을 유지하고 싶을 때 사용하십시오 ./MTd/MDdNDEBUG_DEBUGNDEBUGassert()

고유 한 디버깅 매크로를 정의하고 (컴파일러 또는 C 런타임을 해킹하지 않는 경우) 밑줄로 이름을 시작하지 마십시오.


19
+1. 특히 NDEBUG는 단일 TU 내에서 # undef'd 및 #define '될 수 있습니다 (그리고 <assert.h>를 포함하면 어설 션 매크로가 변경됨). 이것은 예상 / 원하는 것과 다르기 때문에 다른 매크로를 사용하여 "컴파일 전체"디버그 플래그를 제어하는 ​​것이 일반적입니다.

1
분명히 Visual Studio (IDE)가 아닌 이러한 매크로를 정의하는 것은 컴파일러 자체입니다. 이 답변에 감사드립니다!
Niklas R

NDEBUG는 Windows Driver Kit 8.1의 응용 프로그램 템플릿을 사용할 때도 정의되지 않습니다. 이 경우 _DEBUG를 사용해야 할 수도 있습니다.
navossoc

53

NDEBUG가 표준입니까?

예, C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014 표준에 대한 "Not Debug"의미의 표준 매크로입니다. _DEBUG표준 에는 매크로 가 없습니다 .

C ++ 2003 표준은 "17.4.2.1 헤더"의 "326 페이지"에있는 리더를 표준 C로 보냅니다.

NDEBUG는 표준 C 라이브러리와 동일합니다.

"4.2 DIAGNOSTICS"섹션의 C89 (이 표준을 표준 C라고 함)

http://port70.net/~nsz/c/c89/c89-draft.html

포함 된 소스 파일의 지점에서 NDEBUG가 매크로 이름으로 정의되면 어설 션 매크로는 다음과 같이 간단하게 정의됩니다.

     #define assert(ignore) ((void)0)

_DEBUGVisual Studio https://msdn.microsoft.com/en-us/library/b0084kay.aspx 에서 매크로 의 의미를 살펴보면 이 매크로는 언어 런타임 라이브러리 버전 선택에 의해 자동으로 정의됩니다.


50

NDEBUG컴파일러와 구현에서 동작이 표준화 된 유일한 프로그램이기 때문에 에 의존 합니다 (표준 어설 션 매크로에 대한 설명서 참조). 부정적인 논리는 작은 가독성 스피드 범프이지만 빠르게 적용 할 수있는 일반적인 관용구입니다.

비슷한 것에 의존하는 것은 _DEBUG특정 컴파일러 및 라이브러리 구현의 구현 세부 사항에 의존하는 것입니다. 다른 컴파일러는 동일한 규칙을 선택하거나 선택하지 않을 수 있습니다.

세 번째 옵션은 프로젝트에 고유 한 매크로를 정의하는 것입니다. 이는 상당히 합리적입니다. 고유 한 매크로를 사용하면 여러 구현에서 이식성을 제공 할 수 있으며 어설 션과 독립적으로 디버깅 코드를 활성화하거나 비활성화 할 수 있습니다. 일반적으로 컴파일 타임에 활성화되는 다양한 클래스의 디버깅 정보를 사용하지 않는 것이 좋습니다. 왜냐하면 작은 이점을 위해 빌드 (및 테스트) 해야하는 구성 수가 증가하기 때문입니다.

이러한 옵션 중 하나를 사용하여 프로젝트의 일부로 타사 코드를 사용하는 경우 어떤 규칙을 사용하는지 알고 있어야합니다.


1
#if !defined(NDEBUG)<-@HostileFork가 그게 무슨 뜻입니까? #if아닙니다 #ifdef?
Bob Stein

1
@BobStein을 통해 수정 된 원래 의견 : "#ifdef NDEBUG#if !defined(NDEBUG)#ifndef NDEBUG
HostileFork는

17

매크로 NDEBUGassert()명령문의 활성 여부를 제어합니다 .

내 생각에는 다른 디버깅과는 별개이므로 NDEBUG프로그램에서 디버깅 정보를 제어 하는 것 이외의 다른 것을 사용 합니다. 내가 사용하는 것은 작업중인 프레임 워크에 따라 다릅니다. 시스템마다 다른 활성화 매크로가 있으며 적절한 것을 사용합니다.

프레임 워크가 없으면 밑줄없이 이름을 사용합니다. 그것들은 '구현'으로 예약되는 경향이 있으며 이름 충돌과 관련된 문제를 피하려고합니다-이름이 매크로 일 때 두 배로.


왜 다른 유형의 디버깅과 다른 주장을 고려하는지 설명 할 수 있습니까? 어떤 시나리오에서 다른 시나리오를 원하지 않습니까?
Adrian McCarthy

4
다른 디버깅 또는 추적 기능을 코드로 컴파일하지 않아도 어설 션을 활성 상태로 유지합니다. 주장은 불가능한 상황을 식별합니다. 일반적인 추적 및 디버깅은 IMO와 완전히 분리되어 있습니다.
Jonathan Leffler

2
@AdrianMcCarthy : 모든 디버깅이 활성화 된 경우 프로그램이 매우 느리게 실행될 수 있습니다. 따라서 디버깅 유형을 분류하고 사람들이 개별적으로이를 활성화 / 비활성화 할 수 있도록 허용하는 것이 일반적입니다. MSVC에는 표준 라이브러리에 대한 std :: vector와 같은 다양한 디버깅을 활성화 / 비활성화하는 데 사용하는 2-3 개가 있습니다.
Mooing Duck

@MooingDuck : 동의하지만 '사용 가능한 디버깅 및 활성화'와 '사용 가능한 디버깅은 있지만 비활성화'및 '디버깅을 사용할 수 없음'을 구분합니다. 사용 가능 / 사용 불가능한 결정은 컴파일 시간 문제 (C 또는 C ++ 코드)이며, 사용 가능 / 사용 불가능은 디버깅이 가능할 때 런타임 결정입니다. 가장 거친 디버깅 시스템 만 '사용 가능한 수단 활성화'모드에서 작동합니다. (즉, 원유는 효과적 일 수 있으며 야생에서 디버깅 시스템은 엄청나게 많지만 충분히 효과적입니다!)
Jonathan Leffler

2
@MooingDuck : 예, 일부 디버깅 코드는 느리게 변할 수 있습니다. 이 경우 느린 코드가 사소한 검사와 독립적으로 실행되는지 여부를 제어하는 ​​방법 필요할 수 있습니다 . 그러나 이는 한 범주에 명제를, 다른 범주에 #if통제 코드 를 넣는 것과는 다릅니다 . 아마 그렇지 않은 assert(huge_object.IsValid());동안 느려질 수 있습니다 assert(ptr != nullptr);. 나는 대규모 프로젝트에서 로깅추적 이 어설 션과 구별되어야함에 동의 하지만 로깅 또는 추적 을 디버그 코드로 생각하지 않으므로 설명을 요청했습니다.
Adrian McCarthy

6

일관성 있고 어느 것이 중요하지 않습니다. 또한 어떤 이유로 특정 DEBUG 식별자를 사용하여 다른 프로그램이나 도구와 상호 작용 해야하는 경우 쉽게 수행 할 수 있습니다

#ifdef THEIRDEBUG
#define MYDEBUG
#endif //and vice-versa

4

불행히도 DEBUG과부하가 심합니다. 예를 들어, RELEASE 빌드를 위해 항상 pdb 파일을 생성하고 저장하는 것이 좋습니다. 어느 -Zx플래그와 -DEBUG링커 옵션 중 하나를 의미 합니다. 그리고에 대한 _DEBUG호출과 같은 런타임 라이브러리의 특수 디버그 버전 malloc과 관련이 free있습니다. 그런 다음 NDEBUG어설 션을 비활성화합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.