다음을 통해 공유


어설션

어설션 문은 프로그램에 발생할 수 것으로 예상 되는 조건을 지정 합니다.조건이 true 이면 어설션이 실패 하 고 프로그램 실행을 중단 하 고 있는 어설션 오류 대화 상자 나타납니다.

Visual C++에서는 다음 구문을 기반으로 하는 어설션 문을 지원 합니다.

  • MFC 프로그램용 MFC 어설션 합니다.

  • ATL을 사용하는 프로그램용 ATLASSERT

  • C 런타임 라이브러리를 사용하는 프로그램용 CRT 어설션

  • 기타 C/C++ 프로그램용 ANSI assert function

어설션 논리 오류 catch, 작업의 결과 확인 하 고 처리 해야 할 오류 조건 테스트에 사용할 수 있습니다.

항목 내용

어설션의 작동 방법

디버그 및 릴리스 빌드에서 어설션

어설션 사용의 부작용

CRT 어설션

MFC 어설션

  • MFC ASSERT_VALID 및 CObject::AssertValid

  • AssertValid 한계

어설션 사용

  • 논리 오류 catch

  • 결과 확인

  • 찾기 처리 되지 않은 오류

어설션의 작동 방법

MFC 나 C 런타임 라이브러리 어설션으로 인해 디버거가 중지 되 면 소스를 사용할 수 있으면 다음 디버거에서 어설션이 발생 한 위치는 소스 파일에서 이동 합니다.어설션 메시지 모두에 표시 되는 출력 창 , 어설션 오류 대화 상자.어설션 메시지를 출력 창에서 텍스트 창으로 복사해 저장하면 나중에 참조할 수 있습니다.출력 창에 다른 오류 메시지가 있는 경우도 있습니다.이 메시지를 주의 깊게 검토하면 어설션 오류의 원인을 찾을 수 있습니다.

어설션을 사용 하 여 개발 하는 동안 오류를 감지 합니다.일반적으로 각 가정에 대 한 하나의 어설션을 사용 수 있습니다.예를 들어, 인수가 NULL이 아닌지 생각 되 면 어설션 아니라고 테스트에 사용 합니다.

항목 내용

디버그 및 릴리스 빌드에서 어설션

어설션 문은 경우에 컴파일합니다 _DEBUG 정의 됩니다.그렇지 않은 경우 컴파일러는 어설션을 null 문으로 처리 합니다.따라서 어설션 문은 오버 헤드가 없습니다 부과 또는 성능 비용에 최종 릴리스 프로그램을 사용 하지 않도록 할 수 있는 것 #ifdef 지시문입니다.

어설션 사용의 부작용

코드에 어설션을 추가할 경우 어설션에 의도하지 않은 연산이 없는지 확인하십시오.예를 들어, 다음 어설션을 수정 확인 하십시오 있는 nM 값:

ASSERT(nM++ > 0); // Don't do this!

때문에 ASSERT 식 프로그램의 릴리스 버전에서 평가 되지 않습니다 nM 의 디버그 및 릴리스 버전에 서로 다른 값을 갖게 됩니다.MFC에서이 문제를 방지 하려면 사용 된 확인 매크로 대신 ASSERT.VERIFY모든 버전에는 식을 계산 하지만 릴리스 버전에서 결과 확인 하지 않습니다.

함수를 계산할 때 예기치 않은 의도하지 않은 연산이 발생할 수 있으므로 어설션 문에서 함수를 호출할 때는 특히 주의하십시오.

ASSERT ( myFnctn(0)==1 ) // unsafe if myFnctn has side effects
VERIFY ( myFnctn(0)==1 ) // safe

VERIFY호출 myFnctn 의 디버그 및 릴리스 버전에 따라서가 사용할 수 있습니다.그러나 사용 하 여 VERIFY 릴리스 버전에는 불필요 한 함수 호출의 오버 헤드를 부과 합니다.

항목 내용

CRT 어설션

CRTDBG.H 헤더 파일에서 _ASSERT 및 _ASSERTE 매크로를 정의하여 어설션을 확인합니다.

매크로

결과

_ASSERT

지정된 식이 FALSE로 계산될 경우, 결과 값은 _ASSERT의 파일 이름과 줄 번호입니다.

_ASSERTE

_ASSERT와 마찬가지이며, 여기에 어설션된 식의 문자열 표시가 추가됩니다.

_ASSERTE는 결과 값이 FALSE인 어설션된 식을 보고하기 때문에 보다 효과적입니다.따라서 소스 코드를 참조하지 않고도 문제를 식별할 수 있습니다.그러나 응용 프로그램의 디버그 버전에는 _ASSERTE로 어설션된 식마다 문자열 상수가 포함됩니다._ASSERTE 매크로를 많이 사용하면 이러한 문자열 식이 메모리를 많이 차지합니다.문제가 생기면 _ASSERT를 사용하여 메모리를 절약하십시오.

때 _DEBUG 정의 되어 있는 _ASSERTE 매크로 다음과 같이 정의 됩니다:

#define _ASSERTE(expr) \
   do { \
      if (!(expr) && (1 == _CrtDbgReport( \
         _CRT_ASSERT, __FILE__, __LINE__, #expr))) \
         _CrtDbgBreak(); \
   } while (0)

어설션된 식이 FALSE로 계산되면 _CrtDbgReport가 호출되어 어설션 오류를 보고합니다(기본적으로 메시지 대화 상자 사용).선택 하는 경우 재시도 메시지 대화 상자에서 _CrtDbgReport 1을 반환 하 고 _CrtDbgBreak 통해 디버거 호출 DebugBreak.

ww5t02fa.collapse_all(ko-kr,VS.110).gif힙 손상 확인

다음 예제에서는 _CrtCheckMemory를 사용하여 힙 손상을 확인합니다.

_ASSERTE(_CrtCheckMemory());

ww5t02fa.collapse_all(ko-kr,VS.110).gif포인터 유효성 확인

다음 예제에서는 _CrtIsValidPointer를 사용하여 지정한 메모리 범위가 읽기나 쓰기에 적합한지 확인합니다.

_ASSERTE(_CrtIsValidPointer( address, size, TRUE );

다음 예제에서는 _CrtIsValidHeapPointer를 사용하여 로컬 힙에서 포인터가 메모리를 가리키는지 확인합니다. 이때 로컬 힙이란 이러한 C 런타임 라이브러리의 인스턴스가 만들고 관리하는 힙, 즉 DLL에는 라이브러리의 자체 인스턴스가 있으므로 응용 프로그램 힙 외부에 있는 자체 힙을 의미합니다.이 어설션은 null이나 범위를 벗어나는 주소 뿐만 아니라 정적 변수, 스택 변수 및 다른 모든 비 로컬 메모리에 대한 포인터를 찾아 냅니다.

_ASSERTE(_CrtIsValidPointer( myData );

ww5t02fa.collapse_all(ko-kr,VS.110).gif메모리 블록 확인

다음 예제에서는 _CrtIsMemoryBlock을 사용하여 메모리 블록이 로컬 힙에 있고 블록 형식이 유효한지 확인합니다.

_ASSERTE(_CrtIsMemoryBlock (myData, size, &requestNumber, &filename, &linenumber));

항목 내용

MFC 어설션

MFC는 ASSERT 매크로를 정의하여 어설션을 검사합니다.또한 정의 MFC ASSERT_VALID 및 CObject::AssertValid 의 내부 상태를 검사 하는 메서드는 CObject-파생 개체입니다.

경우 MFC의 인수 ASSERT 매크로 평가 0 또는 false 매크로 프로그램 실행을 중지 및 경고 사용자. 그렇지 않으면 실행이 계속 됩니다.

때 메시지 대화 상자에 소스 파일 이름과 어설션 줄 번호가 표시는 어설션이 실패 합니다.대화 상자에서 다시 시도를 선택하면 AfxDebugBreak를 호출하여 프로그램을 중단하고 디버거를 실행합니다.시점에서 호출 스택을 검사 하 고 다른 디버거 기능을 사용 하 여 어설션 실패 한 이유를 확인할 수 있습니다.사용 하도록 설정한 경우 에서 just-in-time 디버깅, 디버거가 이미 실행 하 고 디버거를 시작할 수 있는 대화 상자입니다.

다음 예제에서는 사용 하는 방법을 보여 줍니다. ASSERT 함수의 반환 값을 확인 합니다.

int x = SomeFunc(y);
ASSERT(x >= 0);   //  Assertion fails if x is negative

IsKindOf 함수와 함께 ASSERT를 사용하여 함수 인수의 형식을 확인할 수 있습니다.

ASSERT( pObject1->IsKindOf( RUNTIME_CLASS( CPerson ) ) );

ASSERT 매크로 코드가 릴리스 버전에서을 만듭니다.릴리스 버전에서는 ASSERT 대신 VERIFY 매크로를 사용하여 식을 계산하십시오.

ww5t02fa.collapse_all(ko-kr,VS.110).gifMFC ASSERT_VALID 및 CObject::AssertValid

CObject::AssertValid 메서드는 런타임에 개체의 내부 상태를 검사합니다.CObject에서 클래스를 파생할 때 AssertValid를 반드시 재정의해야 하는 것은 아니지만, 이렇게 하면 클래스의 안정성이 강화됩니다.AssertValid어설션 모든 개체의 멤버 변수를 사용 하 여 유효한 값이 들어 있는지 확인 하에 수행 해야 합니다.예를 들어, 포인터 멤버 변수가 NULL이 아닌지 확인합니다.

다음 예제에서는 AssertValid 함수를 선언하는 방법을 보여 줍니다.

class CPerson : public CObject
{
protected:
    CString m_strName;
    float   m_salary;
public:
#ifdef _DEBUG
    // Override
    virtual void AssertValid() const;
#endif
    // ...
};

AssertValid를 재정의할 때는 AssertValid의 기본 클래스 버전을 먼저 호출하고,다음과 같이 ASSERT 매크로를 사용하여 파생된 클래스의 고유 멤버를 검사하십시오.

#ifdef _DEBUG
void CPerson::AssertValid() const
{
    // Call inherited AssertValid first.
    CObject::AssertValid();

    // Check CPerson members...
    // Must have a name.
    ASSERT( !m_strName.IsEmpty());
    // Must have an income.
    ASSERT( m_salary > 0 );
}
#endif

개체를 저장하는 멤버 변수가 있고 해당 클래스가 AssertValid를 재정의하는 경우, ASSERT_VALID 매크로를 사용하여 내부 유효성을 테스트할 수 있습니다.

예를 들어, CMyData 클래스가 멤버 변수 중 하나에 CObList를 저장할 경우를 고려해 보십시오.CObList 변수 m_DataList는 CPerson 개체 모음을 저장합니다.CMyData의 약식 선언은 다음과 같습니다.

class CMyData : public CObject
{
    // Constructor and other members ...
    protected:
        CObList* m_pDataList;
    // Other declarations ...
    public:
#ifdef _DEBUG
        // Override:
        virtual void AssertValid( ) const;
#endif
    // And so on ...
};

CMyData에서 AssertValid는 다음과 같이 재정의합니다.

#ifdef _DEBUG
void CMyData::AssertValid( ) const
{
    // Call inherited AssertValid.
    CObject::AssertValid( );
    // Check validity of CMyData members.
    ASSERT_VALID( m_pDataList );
    // ...
}
#endif

CMyData는 AssertValid 메커니즘을 사용하여 해당 데이터 멤버에 저장된 개체의 유효성을 테스트합니다.CMyData의 재정의된 AssertValid에서 자체 m_pDataList 멤버 변수에 대해 ASSERT_VALID 매크로를 호출합니다.

유효성 테스트가 중지 되지 않습니다이 수준 때문에 클래스 CObList 또한 재정의 AssertValid.이렇게 재정의하면 목록의 내부 상태 유효성이 추가로 테스트됩니다.따라서 CMyData 개체의 유효성 테스트가 끝나면 저장된 CObList 목록 개체의 내부 상태 유효성이 추가로 테스트됩니다.

목록에 저장된 CPerson 개체에 대한 유효성 테스트도 추가할 수 있습니다.CObList에서 CPersonList 클래스를 파생시키고 AssertValid를 재정의할 수 있습니다.재정의할 때 CObject::AssertValid를 호출한 다음 목록을 반복하여 목록에 저장된 각 CPerson개체의 AssertValid를 호출합니다.이 항목의 시작 부분에 나오는 CPerson 클래스가 이미 AssertValid를 재정의합니다.

이것은 디버깅을 빌드할 때 효과적인 메커니즘입니다.계속해서 릴리스를 빌드할 경우 이 메커니즘은 자동으로 해제됩니다.

ww5t02fa.collapse_all(ko-kr,VS.110).gifAssertValid 한계

어설션이 트리거되면 개체가 잘못된 것이므로 실행이 중지됩니다.그러나 어설션 부족은 발견 된 문제가 있지만 개체 적합 하지 않을 나타냅니다.

항목 내용

어설션 사용

ww5t02fa.collapse_all(ko-kr,VS.110).gif논리 오류 catch

프로그램의 논리에 따라 값이 true인 조건에 어설션을 설정할 수 있습니다.논리 오류가 발생하지 않으면 어설션은 효과가 없습니다.

예를 들어, 컨테이너에서 가스 분자를 시뮬레이션하는 경우 변수 numMols는 총 분자 수를 나타냅니다.이 수는 0 이상이기 때문에 다음과 같이 MFC 어설션 문을 포함할 수 있습니다.

ASSERT(numMols >= 0);

또는 다음과 같이 CRT 어설션을 포함할 수 있습니다.

_ASSERT(numMols >= 0);

프로그램이 제대로 작동하면 이 문은 아무 효과가 없습니다.그러나 논리 오류를 일으키는 경우 numMols 미만으로 0, 어설션이 프로그램의 실행을 중지 하 고 표시 된 어설션 오류 대화 상자.

항목 내용

ww5t02fa.collapse_all(ko-kr,VS.110).gif결과 확인

어설션 작업 결과에서 빠른 눈 명확 하지 않음 테스트 하는 데 유용 합니다.

예를 들어, mols가 가리키는 연결 리스트 내용에 따라 다음과 같이 변수 iMols를 업데이트하는 코드가 있습니다.

/* This code assumes that type has overloaded the != operator
 with const char * 
It also assumes that H2O is somewhere in that linked list. 
Otherwise we'll get an access violation... */
while (mols->type != "H2O")
{
 iMols += mols->num;
 mols = mols->next;
}
ASSERT(iMols<=numMols); // MFC version
_ASSERT(iMols<=numMols); // CRT version

iMols가 계산한 분자 수는 항상 총 분자 수 numMols 이하여야 합니다.루프에서 원하는 결과가 발생하지 않으면 루프 다음에 어설션 문을 사용하여 조건을 테스트하게 됩니다.

항목 내용

ww5t02fa.collapse_all(ko-kr,VS.110).gif찾기 처리 되지 않은 오류

처리할 오류가 있는 코드의 한 지점에서 어설션을 사용하여 오류 조건을 테스트할 수 있습니다.다음 예제에서는 그래픽 루틴이 오류 코드 또는 0을 성공적으로 반환합니다.

myErr = myGraphRoutine(a, b);

/* Code to handle errors and
   reset myErr if successful */

ASSERT(!myErr); -- MFC version
_ASSERT(!myErr); -- CRT version

오류 처리 코드가 제대로 작동하면 오류가 처리되고 어설션에 도달하기 전에 myErr이 0으로 다시 설정되어야 합니다.myErr의 값이 0이 아닌 경우 어설션 오류가 발생하고 프로그램은 중지되며 어설션 오류 대화 상자가 나타납니다.

그러나 어설션 문이 오류 처리 코드를 대체하지는 않습니다.다음 예제는 최종판 코드에서 문제가 될 수 있는 어설션 문을 보여 줍니다.

myErr = myGraphRoutine(a, b);

/* No Code to handle errors */

ASSERT(!myErr); // Don't do this!
_ASSERT(!myErr); // Don't do this, either!

이 코드는 어설션 문에 따라 오류 조건을 처리합니다.따라서 최종판 코드에서는 myGraphRoutine이 반환한 어떠한 오류 코드도 처리되지 않습니다.

항목 내용

참고 항목

참조

관리 코드에 어설션 사용

개념

디버거 보안

기타 리소스

네이티브 코드 디버깅