gcc attribute: nonnull
gcc attribute: nonnull
Reqruies
- Compiler: gcc 3.3 or later
런타임에 동적으로 결정되거나 변수를 거쳐 우회하여 전달되는 NULL은 인지하지 못하는 한계가 있는데, 이 제약 사항에 대해서는 뒤에서 자세히 다루겠습니다.
의도적으로 -Wno-nonnull 옵션을 사용한다면 nonnull 속성을 적용하더라도 컴파일러의 아무런 제지를 받지 않습니다.
GCC 3.3 Changes
GCC 3.3 ChangesDocC/ObjC/C++ ... A new function attribute, nonnull, has been added which allows pointer arguments to functions to be specified as requiring a non-null value. The compiler currently uses this information to issue a warning when it detects a null value passed in such an argument slot.
GCC Documentation
gcc/Common-Function-AttributesDocnonnull (arg-index, …) The nonnull attribute specifies that some function parameters should be non-null pointers. For instance, the declaration: extern void * my_memcpy (void *dest, const void *src, size_t len) attribute((nonnull (1, 2))); causes the compiler to check that, in calls to my_memcpy, arguments dest and src are non-null. If the compiler determines that a null pointer is passed in an argument slot marked as non-null, and the -Wnonnull option is enabled, a warning is issued. The compiler may also choose to make optimizations based on the knowledge that certain function arguments will never be null. If no argument index list is given to the nonnull attribute, all pointer arguments are marked as non-null.
Usage
한 가지 주의할 점은 인자 인덱스 리스트가 0이 아닌
1부터 시작(1-based)한다는 점입니다.Sample Source Code - nonnull.cc
my_test_function()에서 dest와 src 인자가 NULL이어서는 안 된다고 명시했습니다.Build Results
Check Resultbash
Change to error with -Werror=bash
Limitations
이 속성은 앞서 언급했듯, 컴파일 타임에 분석하기 쉬운 상황(주로 명시적 상수 입력)에서만 제한적으로 동작합니다.
Situations that cannot be detectedc
a는 NULL이지만 빌드는 성공합니다.Check Resultbash
a에 명백히 NULL을 담아서 전달했음에도, 상황(최적화 설정 등)에 따라 컴파일러가 이를 즉각적으로 추적하지 못하고 에러 없이 빌드가 성공해버리는 경우가 생깁니다.A More Critical Consideration
nonnull 속성으로 지정된 인자가 절대 NULL이 아닐 것이라고 강하게 확신하며 코드 최적화(Optimization)를 수행합니다.if (dest == NULL) return;)를 불필요한 코드(Dead Code)로 간주하고 컴파일 과정에서 아예 제거해 버릴 수 있는 심각한 위험이 존재합니다.nonnull 속성은 외부 API에서 프로그래머의 뻔한 실수를 컴파일 타임에 잡기엔 훌륭하지만, 그 속성이 여러분 내부 구현의 안전성을 100% 보장하는 만능열쇠는 아님을 반드시 인지해야 합니다.Implicitly marking all arguments
Use without argument index listc
Check Result - build failbash
Conclusion
runtime overhead가 전혀 없으므로, 앞으로도 이러한 속성들을 적극적으로 활용하는 것을 추천합니다.