assert에 맞춤 메시지를 추가 하시겠습니까?


129

assert가 던진 메시지를 추가하거나 편집하는 방법이 있습니까? 나는 같은 것을 사용하고 싶습니다

assert(a == b, "A must be equal to B");

그런 다음 컴파일러는 line , time 등을 추가합니다 ...

가능합니까?


당신은 같은 매크로를 정의 할 수 있습니다 .
HelloGoodbye

답변:


240

내가 본 해킹은 &&연산자 를 사용하는 것 입니다. 널이 아닌 경우 포인터가 "참"이므로 조건을 변경하지 않고 다음을 수행 할 수 있습니다.

assert(a == b && "A is not equal to B");

이후 assert쇼에 실패하는 조건, 너무 당신의 메시지를 표시합니다. 충분하지 않으면 myAssert원하는 것을 표시하는 자체 함수 또는 매크로를 작성할 수 있습니다 .


27
또 다른 옵션은 피연산자를 뒤집고 쉼표 연산자를 사용하는 것입니다. 추가 괄호가 필요하므로 쉼표가 인수 사이의 구분자로 취급되지 않습니다.assert(("A must be equal to B", a == b));
Keith Thompson

3
그러나 변수 값을 다음과 같이 인쇄 할 수 있으면 좋을 것입니다.assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
Frank

7
@Frank printf는 아무것도 인쇄하지 않으면 0이 아닌 값을 반환하므로 assert(a == b && printf("a (%i) is not equal to b (%i)", a, b)), 당신은 아마도 자신의 assert wrapper를 작성해야합니다.
zneak

1
나쁜 코드! 나는 이것을 이해하지 못한다! a == b가 false이면 and-expression도 false 여야하므로 문자열을 평가하지 않아야합니다.
ragnarius

1
@TUIlover, C 문자열 리터럴이 작동하는 방식이 아닙니다. 그것들은 컴파일 타임 상수 이며이 맥락에서의 사용은 사소하게 최적화됩니다. 런타임 비용이 없습니다.
zneak

45

또 다른 옵션은 피연산자를 뒤집고 쉼표 연산자를 사용하는 것입니다. 추가 괄호가 필요하므로 쉼표가 인수 사이의 구분자로 취급되지 않습니다.

assert(("A must be equal to B", a == b));

(이것은 더 나은 가시성을 위해 위의 주석에서 복사되었습니다)


3
이것은 작은 접근 방식을 가진 훌륭한 접근 방법입니다.`-Wunused-value
v010dya

1
또는 매크로 : #ifndef m_assert #define m_assert (expr, msg) assert ((msg, expr)) #endif
Szymon Marczak

매크로 래퍼를 사용하면 gcc 경고를 피할 수 있습니다.#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
Jander

25

다음은 메시지를 수락하고 모든 것을 명확한 방식으로 인쇄하는 assert 매크로의 내 버전입니다.

#include <iostream>

#ifndef NDEBUG
#   define M_Assert(Expr, Msg) \
    __M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
#else
#   define M_Assert(Expr, Msg) ;
#endif

void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
{
    if (!expr)
    {
        std::cerr << "Assert failed:\t" << msg << "\n"
            << "Expected:\t" << expr_str << "\n"
            << "Source:\t\t" << file << ", line " << line << "\n";
        abort();
    }
}

이제 이것을 사용할 수 있습니다

M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");

그리고 실패하는 경우 다음과 같은 메시지가 나타납니다.

어설 션 실패 : MyFunction : 널이 아닌 인수 필요

예상 : ptr! = nullptr

출처 : C : \ MyProject \ src.cpp, 22 행

친절하고 깨끗하며 코드에서 자유롭게 사용하십시오 =)


좋은데 매우 유용
Killrazor

조금 혼란 스러워요. #Expr은 직접 대체 문자열로 취급됩니까? #Expr과 Expr의 차이점은 무엇입니까?
Minh Tran

@MinhTran 당신의 주장 조건이이라고 가정하자 x == y. 그러면 Expr이 확장되고 if( !(x == y))여기에서 조건이 확인되고 #Expr이 string literal으로 확장 "x == y"되어 오류 메시지가 표시됩니다.
Eugene Magdalits

불행하게도,이 솔루션은 예약 된 식별자를 사용하여 정의되지 않은 동작을 유발합니다.
Monica

19
BOOST_ASSERT_MSG(expre, msg)

http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html

직접 사용하거나 Boost의 코드를 복사 할 수 있습니다. 또한 Boost assert는 헤더 전용이므로 모든 Boost를 설치하지 않으려는 경우 해당 단일 파일을 가져올 수 있습니다.


@Jichao, assert 인터페이스를 구현한다는 것은 무엇을 의미합니까?
Tarc

7

zneak의 답변이 코드를 다소 복잡하게 만들므로 더 나은 접근 방식은 단순히 말하는 문자열 텍스트에 주석을 달는 것입니다. 즉 :

assert(a == b); // A must be equal to B

assert 오류의 독자는 오류 메시지에서 파일과 행을 조회하므로 여기에서 전체 설명을 볼 수 있습니다.

하루가 끝날 때 이렇게 :

assert(number_of_frames != 0); // Has frames to update

이것보다 더 잘 읽습니다.

assert(number_of_frames != 0 && "Has frames to update");

코드의 인간 파싱 측면에서 가독성. 언어 해킹도 아닙니다.


1
"어설 션 오류를 읽는 사람은 오류 메시지에서 파일과 행을 조회하기 때문에 부지런한 경우에만 해당됩니다."
Jason S

그들이 버그를 고치려는 경우에만 당신은 ... 어리석은 말
변태

1
아닙니다. 사람들이 문제를보다 쉽게 ​​볼 수있게하면 행동을 취할 가능성이 높아집니다.
Jason S

어깨를 으 Dis하다.
변태

2

assert는 매크로 / 함수 조합입니다. 당신은 사용하여 자신 만의 매크로 / 함수를 정의 할 수 있습니다 __FILE__, __BASE_FILE__, __LINE__사용자 정의 메시지를 취 자신의 기능 등


-6

vc의 경우 assert.h에 다음 코드를 추가하십시오.

#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )

11
컴파일러의 헤더를 수정하는 것은 좋지 않습니다.
로스 릿지
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.