programing

C 경고 함수 호출에 sentinel이 없습니다.

goodsources 2022. 7. 11. 21:32
반응형

C 경고 함수 호출에 sentinel이 없습니다.

이건 경고야.

Missing sentinel in function call

어떻게 제거할 수 있는지.

Linux & gcc 컴파일러를 사용하고 있습니다.

방금 같은 문제를 발견했어요.그 원인이 된 암호는...

execl("/bin/bash", "/bin/bash", fname, '\0');

하지만 그건...

execl("/bin/bash", "/bin/bash", fname, (char *)0);

첫 번째 버전의 문제는 파라미터 목록이 늘포인터로 끝나는 것입니다.그러나 '\0'은 null 포인터가 아니라 null 문자입니다.따라서 값(0)이 올바르고 유형이 잘못된 것일 뿐입니다.

(char *)0도 0이지만 늘 포인터(주소0을 가리키고 있음)인 char 포인터로 캐스트됩니다.이는 파라미터 리스트가 끝나는 곳을 시스템이 알 수 있도록 하기 위해 필요합니다.이것에 의해, 시스템은 마지막 리스트 후에 파라미터를 스캔 하지 않게 됩니다.이렇게 하면 잘못된 포인터가 수신되어 메모리를 가리킬 수 있으며, 이는 분할 장애를 일으킬 수 있습니다.

이 (char *)0은 Sentinel이라고 불리며 첫 번째 예에서 누락된 것입니다.

마지막으로 NULL은 (void *)0으로 정의되므로

execl("/bin/bash", "/bin/bash", fname, NULL);

마찬가지로 동작도 좋고, 조금 편리합니다.(@mah 덕분에)

것 .NULL 실행 시 수 가 시작되므로 할 수 null이 없으면 실행 시 어레이의 끝부분과 다음 메모리의 시작부분을 알 수 없기 때문에 메모리가 이상할 수 있습니다.

(void*)0 ★★★★★★★★★★★★★★★★★」(void *)NULLNULL

경고는 이 경고에 의해 됩니다.sentinel지차오가 언급한 기능 속성.문서: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html#index-g_t_0040code_007bsentinel_007d-function-attribute-3226 에서 다음 내용을 확인할 수 있습니다.

이 컨텍스트에서 유효한 NULL은 모든 포인터 유형에 대해 0으로 정의됩니다.시스템에서 정수 유형을 사용하여 NULL 매크로를 정의하는 경우 명시적 캐스트를 추가해야 합니다.GCC가 stdef를 대체합니다.h는 NULL을 적절히 재정의하는 복사본입니다.

은 ANSI C의 NULL로 할 수 .0 ★★★★★★★★★★★★★★★★★」(void *)0단, 포인터만이 이 Atribute를 만족합니다.다음도 참조해 주세요.NULL, '\0'과 0의 차이점은 무엇입니까?

한편, 「 」는, 「 」, 「 」의 사이에0정규 포인터 인수에 의해 늘 포인터에 캐스트 됩니다.제로 포인터와 제로 포인터를 vararg로 구별하는 것은 불가능하기 때문에 차이는 매우 중요합니다.참조: 포인터의 기본 인수 승격

물론 GCC는 NULL이 포인터임을 보증합니다.NULL은 GCC에 의해 제공되기 때문에stddef.h(일부 ANSI C 헤더는 GCC에 있고 다른 헤더는 glibc에 있습니다).이것이 깨질지 어떨지는 모르겠습니다.sentinel는 처음에 GCC 확장입니다.

하지만 난 여전히 글을 쓸 거야(void *)NULL또는(void*)0혹시 모르니까

또한 POSIX와man execlsentinel 사용의 프로토타입인 execl() 함수 종료를 위해 "null pointer"가 필요합니다.

NULL는 반드시 "null 포인터"가 아닌 "null pointer constant"이기 때문에 여기서 동작하는 것은 보증되지 않습니다.(void *)0어디서든 잘 알려진 API로 일관성을 유지할 수 있습니다.참고 항목: (void*)0)은 늘 포인터 상수입니까?|| (int *)0은 늘 포인터입니까?

GCC 5.2.0은execl 빌트인세트로서sentinel프로그래밍 방식으로:

DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECL, "execl", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_SENTINEL_NOTHROW_LIST)

glibc 2.21 버전도 있습니다.execlAtribute가 없습니다.

NULL은 execl("/bin/bash", "ls", -l", NULL로 전달할 수 있습니다.마지막 매개 변수는 항상 0이어야 합니다.NULL 터미네이터입니다.인수 목록은 가변적이기 때문에 C에게 언제 끝날지 알려주는 방법이 있어야 합니다.

간단한 예:

#include <stdio.h>
#include <stdarg.h>

void print_strings(const char* first, ...) __attribute__((sentinel));

void print_strings(const char* first, ...)
{
    va_list ap;
    const char* tmp;
    if (!first)
        return ;
    printf("%s\n", first);
    va_start(ap, first);
    while (1) {
        tmp = va_arg(ap, const char*);
        if (tmp == 0)
            break;
        printf("%s\n", tmp);
    };
    va_end(ap);
}

int main()
{
    print_strings("how are you?", "i'm fine", "and you?", NULL);
    return 0;
}

기본적으로 print_strings를 다음과 같이 호출하면print_strings("how are you?", "I'm fine", "and you?")끝이 없는NULL, GCC는 「센티넬의 누락」을 호소합니다.

sentinel 함수 속성을 함수에 추가하기 때문입니다.print_strings변수 인수가 NULL로 끝나도록 지정하는 gcc 확장입니다. 따라서 변수 인수가 NULL로 끝나지 않으면 컴파일러가 이를 검출하여 경고를 표시할 수 있습니다.

보초병은 지키거나 보호하는 것을 의미합니다.따라서 이 컨텍스트에서는 가드 파라미터가 누락되어 있을 수 있기 때문에 에러가 발생하고 있습니다.배열 또는 사전을 사용하는 경우 오브젝트 이름 지정 후 키워드 0으로 끝나는지 확인합니다.

예:

[NSDictionary dictionaryWithObjectsAndKeys:@"UIAlertView", kSectionTitleKey,
              @"Show Custom", kLabelKey,
              @"AlertsViewController.m - alertOtherAction", kSourceKey];

위의 문에서는 "함수 호출에 sentinel이 없습니다"라는 오류가 발생합니다.

올바른 구문:

[NSDictionary dictionaryWithObjectsAndKeys:@"UIAlertView", kSectionTitleKey,
              @"Show Custom", kLabelKey,
              @"AlertsViewController.m - alertOtherAction",kSourceKey,nil];

나는 마침내 이 이상하고 짜증나는 경고를 없앨 방법을 찾았다.

적절한 포인터 타입에 영점 포인터를 던지기만 하면 됩니다.

의 경우UIAlertView그건 이런 식이다:

UIAlertView* alert = [ [ UIAlertView alloc ] initWithTitle: @"Title" message: @"Message" delegate: nil cancelButtonTitle: @"Cancel" otherButtonTitles: @"OK", ( NSString* )nil ];

주의:( NSString* )nil

한 번 시도해보고 이것이 당신에게 적합한지 알려주세요.

Xcode에서 objective-c로 코딩하고 변수 파라미터 목록을 사용하는 메서드를 사용하는 경우 목록 끝에 0 개체를 추가해야 합니다.

예를 들어 다음과 같습니다.

NSAray * names = [NSArray arrayWithObjects: @"Name1", @"Name2"; //위의 경고가 표시됩니다.

단, NSAray *names = [NSArray 어레이 WithObjects: @"Name1", @"Name2", nil]; //정답

이게 도움이 되길 바라!

해야 한다NULL함수의 마지막 인수입니다.

언급URL : https://stackoverflow.com/questions/2407605/c-warning-missing-sentinel-in-function-call

반응형