어설션(소프트웨어 개발)

Assertion (software development)

컴퓨터 프로그래밍에서, 특히 명령형 프로그래밍 패러다임을 사용할 때, 어설션은 프로그램의 한 지점에 연결된 술어(통상적으로 프로그램의 변수를 사용하여 논리적인 명제로 표현되는 상태 공간에 대한 부울 값 함수)이며, 코드 실행의 그 지점에서 항상 참으로 평가되어야 한다.어설션은 프로그래머가 코드를 읽거나 컴파일러가 코드를 컴파일하거나 프로그램 자체의 결함을 검출하는 데 도움을 줄 수 있습니다.

후자의 경우 일부 프로그램은 실행할 때 술어를 실제로 평가하여 어사션을 확인합니다.그 후, 그것이 사실이 아닌 경우(어설션 실패), 프로그램은 스스로를 파손된 것으로 간주하고, 일반적으로 의도적으로 어설션 실패 예외를 발생시키거나 합니다.

세부 사항

다음 코드에는 두 가지 어소션이 포함되어 있습니다.x > 0그리고.x > 1실행 중 지시된 시점에서 실제로 해당됩니다.

x = 1; 주장하다 x > 0; x++; 주장하다 x > 1; 

프로그래머는 어설션을 사용하여 프로그램을 지정하고 프로그램의 정확성을 추론할 수 있습니다.예를 들어, 전제 조건(코드 섹션의 선두에 배치된 어설션)은 프로그래머가 코드가 실행될 것으로 예상하는 일련의 상태를 결정합니다.post condition(마지막에 배치됨)은 실행 종료 시 예상되는 상태를 나타냅니다.예를 들어 다음과 같습니다.x > 0 { x++ } x > 1.

위의 예에서는 C가 사용하는 어사션을 포함하기 위한 표기를 사용하고 있습니다. 1969년 [1]A. R. Hoare 기사에서이 표기법은 기존의 주류 프로그래밍 언어에서는 사용할 수 없습니다.그러나 프로그래머는 프로그래밍 언어의 주석 기능을 사용하여 선택되지 않은 주장을 포함할 수 있습니다.를 들어, C:

x = 5; x = x + 1; // {x > 1 } 

코멘트에 포함된 중괄호는 코멘트의 이러한 사용을 다른 용도와 구별하는 데 도움이 됩니다.

라이브러리는 어설션 기능도 제공할 수 있습니다.예를 들어, C99 지원에서 glibc를 사용하는 C의 경우:

#실패하다 <고객명>님.h>  인트 f(무효) {     인트 x = 5;     x = x + 1;     주장하다(x > 1); } 

몇 가지 최신 프로그래밍 언어에는 체크된 어사션이 포함되어 있습니다., 실행 시 또는 정적으로 체크되는 문장이 있습니다.런타임에 어설션이 false로 평가되면 어설션 실패가 발생하여 일반적으로 실행이 중단됩니다.이로 인해 논리적인 부정합이 검출되는 장소에 관심이 집중되며, 그렇지 않으면 발생할 수 있는 동작보다 바람직할 수 있습니다.

어설션의 사용은 프로그래머가 프로그램을 설계, 개발 및 추론하는 데 도움이 됩니다.

사용.

에펠과 같은 언어에서 어설션은 설계 프로세스의 일부를 형성합니다.C나 Java같은 다른 언어들은 실행 시 가정을 확인하는 데만 사용합니다.두 경우 모두 실행 시 유효성을 확인할 수 있지만 일반적으로 억제할 수도 있습니다.

계약에 의한 설계상의 주장

어설션은 문서의 한 형태로 기능할 수 있습니다.어설션은 코드가 실행되기 전에 찾을 것으로 예상되는 상태(전제 조건) 및 코드가 실행이 종료되었을 때 발생할 것으로 예상되는 상태( 조건)를 기술할 수 있습니다.또한 클래스의 불변성을 지정할 수도 있습니다.에펠은 이러한 주장을 언어에 통합하고 자동으로 추출하여 수업을 문서화합니다.이것은 계약에 의한 설계 방법의 중요한 부분을 형성한다.

이 접근방식은 명시적으로 지원하지 않는 언어에서도 유용합니다.코멘트 내의 어설션보다 어설션 스테이트먼트를 사용하는 장점은 프로그램이 실행될 때마다 어설션을 체크할 수 있다는 것입니다.어설션이 더 이상 유지되지 않으면 오류가 보고될 수 있습니다.이렇게 하면 코드가 어설션과 동기화되지 않습니다.

런타임 확인을 위한 어설션

어설션은 프로그램 실행 중에 프로그래머에 의해 이루어진 가정이 프로그램이 실행되었을 때 유효한지를 검증하기 위해 사용될 수 있다.예를 들어 다음 Java 코드를 생각해 보겠습니다.

 인트  = Count Of Users();  한다면 ( % 2 == 0) {      // 합계는 짝수입니다.  } 또 다른 {      // 합계가 홀수이며 음수가 아닙니다.      주장하다  % 2 == 1;  } 

자바에서는%나머지 연산자(modulo)이며, Java에서는 첫 번째 피연산자가 음수인 경우에도 결과가 음수일 수 있습니다(수학에 사용되는 modulo와 다름).여기서 프로그래머는 다음과 같이 가정했다.total는 음이 아닙니다.따라서 2를 가진 나눗셈의 나머지 부분은 항상 0 또는 1이 됩니다.이 주장은 다음과 같은 가정을 명확히 한다.countNumberOfUsers음의 값을 반환합니다.프로그램에 버그가 있을 수 있습니다.

이 기술의 주요 장점은 오류가 발생했을 때 종종 불분명한 효과를 통해 나중에 감지되는 것이 아니라 즉시 그리고 직접적으로 감지된다는 것입니다.어설션 실패는 보통 코드 위치를 보고하기 때문에 더 이상 디버깅하지 않고 오류를 특정할 수 있습니다.

또한 어설션은 실행이 도달해서는 안 되는 지점에 배치되는 경우도 있습니다.예를 들어, 어설션은 다음 위치에 배치할 수 있습니다.default의 조항switchC, C++, Java 의 언어로 된 스테이트먼트.프로그래머가 의도적으로 처리하지 않은 경우 오류가 발생하고 프로그램이 잘못된 상태로 조용히 계속되지 않고 중단됩니다.D에서 그러한 주장은 다음과 같은 경우에 자동으로 추가됩니다.switch스테이트먼트에는 다음 항목이 포함되지 않습니다.default절을 클릭합니다.

Java에서 어설션은 버전 1.4부터 언어의 일부였습니다.어설션 실패는 다음 명령어를 발행하는 원인이 됩니다.AssertionError프로그램이 적절한 플래그를 사용하여 실행되며, 이 플래그가 없으면 아사트 문장이 무시됩니다.C에서는 표준 헤더에 의해 추가됩니다.assert.h정의 assert (assertion) 일반적으로 프로그램을 종료하고 실패 시 오류를 알리는 매크로로 사용됩니다.C++에서는 둘 다assert.h그리고.cassert헤더는assert매크로를 사용합니다.

어설션의 위험은 메모리 데이터를 변경하거나 스레드 타이밍을 변경함으로써 부작용을 일으킬 수 있다는 것입니다.주장은 프로그램 코드에 부작용을 일으키지 않도록 신중하게 구현되어야 합니다.

언어의 어설션 구조를 사용하면 서드파티 라이브러리를 사용하지 않고도 TDD(Test-Drived Development)를 쉽게 실행할 수 있습니다.

개발 사이클 중의 어설션

개발 주기 동안 프로그래머는 일반적으로 어설션을 활성화하여 프로그램을 실행합니다.어설션 실패가 발생하면 프로그래머에게 즉시 문제가 통지됩니다.많은 어설션 실장에서는 프로그램의 실행도 정지됩니다.어설션 위반이 발생한 후에도 프로그램이 계속 실행되면 상태가 손상되어 문제의 원인을 찾기 어려워질 수 있기 때문에 유용합니다.어설션 실패에 의해 제공되는 정보(예: 장애 위치 및 스택 트레이스, 또는 환경이 코어 덤프를 지원하거나 프로그램이 디버거에서 실행 중인 경우 전체 프로그램 상태)를 사용하면 프로그래머는 보통 문제를 해결할 수 있습니다.따라서 어설션은 디버깅에서 매우 강력한 도구를 제공합니다.

실가동 환경에서의 주장

프로그램이 실전에 배치될 때, 어설션은 일반적으로 오버헤드나 부작용을 피하기 위해 꺼집니다.매크로를 통한 C/C++ 어설션 등 전개된 코드에는 어설션이 전혀 없는 경우가 있습니다.Java와 같은 다른 경우 전개된 코드에 아사션이 존재하며 [2]디버깅을 위해 필드에서 설정할 수 있습니다.

어설션은 주어진 에지 조건이 실제로 도달할 수 없다는 것을 컴파일러에 약속하기 위해 사용될 수 있으며, 따라서 다른 방법으로는 가능하지 않은 특정 최적화를 허용할 수 있습니다.이 경우 어설션을 디세블로 하면 실제로 퍼포먼스가 저하될 수 있습니다.

정적 어설션

컴파일 시에 체크되는 어사션을 스태틱어사션이라고 부릅니다

정적 어사션은 컴파일 시간 템플릿 메타프로그래밍에서 특히 유용하지만 어사션이 실패했을 경우에만 잘못된 코드를 도입함으로써 C와 같은 저수준 언어에서도 사용할 수 있습니다.C11C++11은 를 통해 스태틱어사션을 직접 지원합니다.static_assert이전 C 버전에서는 다음과 같이 정적 어설션을 구현할 수 있습니다.

#정의 SASERT(pred) 스위치(0){case 0:case pred:;}  새서트( 부울 조건. ); 

이 경우,(BOOLEAN CONDITION)파트가 false로 평가되면 컴파일러가 동일한 상수의 2개의 케이스 라벨을 허용하지 않기 때문에 위의 코드는 컴파일되지 않습니다.부울식은 예를 들어 컴파일 시간 상수 값이어야 합니다.(sizeof(int)==4)그런 맥락에서 유효한 표현일 것입니다.이 구성은 파일 범위(즉, 함수 내부가 아님)에서 작동하지 않으므로 함수 내부로 래핑해야 합니다.

C에서 어설션을 구현하는 또 다른 일반적인 방법은[3] 다음과 같습니다.

정적인  컨스턴트 static_displays(스태틱_displays)[ (부울 조건.)                                     ? 1 : -1                                   ] = {'!'}; 

이 경우,(BOOLEAN CONDITION)파트가 false로 평가되면 배열의 길이가 음수일 수 없기 때문에 위의 코드는 컴파일되지 않습니다.컴파일러가 음의 길이를 허용하는 경우 초기화 바이트('!'part)는 이러한 과도한 컴파일러가 불만을 제기하는 원인이 됩니다.부울식은 예를 들어 컴파일 시간 상수 값이어야 합니다.(sizeof(int) == 4)그런 맥락에서 유효한 표현일 것입니다.

두 방법 모두 고유한 이름을 구성하는 방법이 필요합니다.최신 컴파일러는__COUNTER__프리프로세서는 각 컴파일 [4]유닛에 대해 단조롭게 증가하는 번호를 반환함으로써 고유한 이름의 구성을 용이하게 하는 정의입니다.

D는 다음을 사용하여 정적 어사션을 제공합니다.static assert를 클릭합니다.[5]

어설션 비활성화

대부분의 언어에서는 아사션을 글로벌하게 활성화 또는 비활성화할 수 있으며 경우에 따라 독립적으로 활성화할 수 있습니다.어설션은 개발 중에 활성화되고 최종 테스트 중에 비활성화되어 고객에게 출시되는 경우가 많습니다.주장을 확인하지 않으면 (주장에 부작용이 없다고 가정할 때) 정상적인 조건에서 동일한 결과를 생성하는 동안 주장을 평가하는 비용을 피할 수 있다.비정상적인 상황에서 어설션 체크를 비활성화하면 중단된 프로그램이 계속 실행될 수 있습니다.이 방법이 더 좋을 수 있습니다.

C 및 C++ 의 일부 언어에서는 프리프로세서를 사용하여 컴파일 시 어사션을 완전히 삭제할 수 있습니다.

마찬가지로 Python 인터프리터를 인수로 "-O"("최적화"의 경우)로 시작하면 Python 코드 생성기가 [6]어설트용 바이트 코드를 내보내지 않습니다.

Java는 어설션을 활성화하기 위해 런타임엔진에 옵션을 전달해야 합니다.옵션이 없으면 어설션은 바이패스되지만 런타임에 JIT 컴파일러에 의해 최적화되거나 프로그래머가 수동으로 각 어설션을 뒤에 배치하여 컴파일 시에 제외되지 않는 한 항상 코드에 남아 있습니다.if (false)절을 클릭합니다.

프로그래머는 언어의 정상적인 어설션 체크 메커니즘을 우회하거나 조작함으로써 항상 활성화된 코드에 체크를 내장할 수 있습니다.

오류 처리와의 비교

어설션은 일상적인 오류 처리와는 다릅니다.어설션은 논리적으로 불가능한 상황을 기록하고 프로그래밍 오류를 발견합니다.불가능한 상황이 발생하면 프로그램에 근본적인 문제가 있는 것이 분명합니다.이것은 에러 처리와는 다릅니다.실제로 발생할 가능성이 극히 낮은 에러도 있습니다만, 대부분의 에러 상태가 발생할 가능성이 있습니다.어설션을 일반적인 오류 처리 메커니즘으로 사용하는 것은 현명하지 않습니다.어설션에서는 에러로부터의 회복이 허용되지 않습니다.어설션의 실패는 보통 프로그램의 실행을 갑자기 정지시킵니다.또한 어설션은 종종 프로덕션 코드에서 비활성화됩니다.또한 어설션에서는 사용자에게 친숙한 오류 메시지가 표시되지 않습니다.

다음 예에서는 어설션을 사용하여 오류를 처리하는 방법을 검토합니다.

  인트 *ptr = 마로크(크기(인트) * 10);   주장하다(ptr);   // ptr 사용   ... 

여기서 프로그래머는 알고 있습니다.malloc메모리가 할당되지 않은 경우 포인터를 반환합니다.이것은 가능합니다.운영체제가 모든 콜을malloc성공할 것이다.메모리 부족 에러가 발생했을 경우, 프로그램은 즉시 중단됩니다.어설션이 없으면 프로그램은 다음 시간까지 계속 실행됩니다.ptr사용되는 특정 하드웨어에 따라 참조가 취소되고 더 길어질 수 있습니다.어설션이 무효가 되어 있지 않은 한, 즉시 종료가 보증됩니다.단, 정상적인 장애가 필요한 경우 프로그램은 장애를 처리해야 합니다.예를 들어 서버에 여러 클라이언트가 있거나 정상적으로 릴리스되지 않는 리소스를 보유하고 있거나 데이터스토어에 쓰기 위해 커밋되지 않은 변경 사항이 있을 수 있습니다.이러한 경우 갑자기 중단하는 것보다 단일 트랜잭션에 실패하는 것이 좋습니다.

또 다른 오류는 어설션의 인수로 사용되는 표현의 부작용에 의존하는 것이다.주장의 유일한 목적은 항상 참이어야 하는 조건이 실제로 참임을 확인하는 것이기 때문에 주장이 전혀 실행되지 않을 수도 있다는 것을 항상 염두에 두어야 한다.따라서 프로그램이 오류가 없는 것으로 간주되고 릴리스되면 어설션이 비활성화되어 더 이상 평가되지 않을 수 있습니다.

이전 예의 다른 버전을 검토합니다.

  인트 *ptr;   // malloc()가 NULL을 반환하는 경우 아래 문장은 실패합니다.   // 단, -NDEBUG로 컴파일 할 때는 전혀 실행되지 않습니다!   주장하다(ptr = 마로크(크기(인트) * 10));   // - NDEBUG로 컴파일할 때 ptr을 사용: ptr이 초기화되지 않음!   ... 

이 방법은 반환값을 할당하는 현명한 방법처럼 보일 수 있습니다.malloc로.ptr체크해 주세요NULL한 걸음으로, 하지만malloc호출 및 할당ptr를 형성하는 표현 평가의 부작용입니다.assert조건.언제?NDEBUG파라미터가 컴파일러에 전달됩니다.프로그램이 에러 없는 것으로 간주되어 해방되었을 때,assert()스테이트먼트가 삭제되기 때문에malloc()호출되지 않음, 렌더링ptr초기화되지 않았습니다.이로 인해 잠재적으로 프로그램 실행에서 훨씬 더 먼 곳에서 분할 오류 또는 유사한 늘 포인터 오류가 발생할 수 있으며, 이로 인해 버그가 산발적으로 발생하거나 추적하기 어려울 수 있습니다.프로그래머는 이 문제를 완화하기 위해 유사한 VERIFY(X) 정의를 사용하는 경우가 있습니다.

최신 컴파일러에서는 위의 [7]코드가 검출되면 경고가 발생할 수 있습니다.

역사

폰 노이만 Goldstine[8]으로 IAS는 기계에 그들의 디자인에 1947년 보고서에서, 그들은 알고리즘은 그들이 주장:`` 때마다 C은 실제로는 흐름도의 특정한 지점에 이르면 하나 이상의 바인딩 된 변수 반드시 특정 values, 가질 것이다 사실이 될 수 있는지 포함된 플로우 차트,의 초기 버전을 사용하여 묘사했다.또는특정 특성을 가지거나 서로 특정 특성을 만족시킵니다.또, 이 시점에서, 이러한 제한의 유효성을 나타낼 수도 있습니다.이러한 이유로 우리는 그러한 제한의 타당성이 주장되고 있는 각 영역을 어설션 박스라고 하는 특별한 박스로 나타낼 것입니다."

프로그램의 정확성을 증명하기 위한 주장적 방법은 앨런 튜링에 의해 주장되었다.1949년 6월 24일 캠브리지에서 열린 "Checking a Large Routine"이라는 강연에서 튜링은 다음과 같이 제안했다. "어떻게 사람이 그것이 맞는지 확인하는 의미에서 큰 루틴을 확인할 수 있는가?체크하는 사람이 너무 어려운 작업을 하지 않도록 프로그래머는 개별적으로 체크할 수 있고 프로그램 전체의 정확성이 쉽게 따라올 수 있는 여러 가지 명확한 주장을 해야 한다.[9]

「 」를 참조해 주세요.

레퍼런스

  1. ^ C. A. R. Hoare, 컴퓨터 프로그래밍의 자명한 기초, Communications of the ACM, 1969.
  2. ^ 아사션을 사용한 프로그래밍, 아사션 활성화비활성화
  3. ^ 존 재거, C, 1999년 시간 어설션 컴파일
  4. ^ GNU, "GCC 4.3 릴리즈 시리즈 - 변경, 신기능 및 수정"
  5. ^ "Static Assertions". D Language Reference. The D Language Foundation. Retrieved 2022-03-16.
  6. ^ 공식 Python Docs, assert 스테이트먼트
  7. ^ "Warning Options (Using the GNU Compiler Collection (GCC))".
  8. ^ 골드스틴과 폰 노이만입니다"전자 컴퓨팅 기기의 문제 계획코드화"제2부, 제1권, 1947년 4월 1일, 12페이지
  9. ^ 앨런 튜링.1949년, C. A. R. Hoare에 인용된 "황제의 낡은 옷", 1980년 튜링상 강연.

외부 링크