2017-01-31 5 views
1

로깅 도우미 기능에서 strerror_r을 사용하고 있습니다. 설명서 페이지에서 설명하는 것처럼이 함수에는 두 가지 버전이 있습니다. POSIX 버전은 int를 반환합니다. GNU 버전은 문자열 (char *)을 반환합니다. 이와 같이알파로 리눅스에서 strerror_r이 잘못 선언되었습니다.

, 내 C++ 코드를 더 휴대용이다, 나는이 비슷한 코드 블록 그래서 : 위의 코드 블록에서

char buffer[1000]; 
    int size = 1000; 
    int result = 0; 
    char* msg = buffer; 
    buffer[0] = '\0'; 
#ifdef _GNU_SOURCE 
    msg = strerror_r(err, buffer, size); 
#else 
    result = strerror_r(err, buffer, size); 
    if (result != 0) 
    { 
     sprintf(buffer, "unknown error: %d", err); 
    } 
#endif 
    LogToFile(msg); 

를, 그것은 존재에 따라 strerror_r의 버전 중 하나를 사용합니다 _GNU_SOURCE인데, libstdC++에서 필요하기 때문에 항상 g ++로 설정됩니다. Mac 및 Unix의 다른 변형에서는 POSIX 버전을 사용합니다.

이제이 코드는 오늘까지 오랫동안 잘 진행되어 왔습니다. 사용자는 Alpine Linux에 내 코드를 컴파일하려고하고이 라인에 매핑 strerror_r

main.cpp:16:21 error: invalid conversion from 'int' to 'char*' [-fpermissive] 

사용하여 라인에 오늘이 컴파일러 오류를보고 :

#ifdef _GNU_SOURCE 
    msg = strerror_r(err, buffer, size); 

알이 플랫폼에 /usr/include/string.h에서 피크 촬영을 다음과 같습니다 :

#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ 
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ 
|| defined(_BSD_SOURCE) 
... 
int strerror_r (int, char *, size_t); 
... 
#endif 

어떤 컴파일러 환경이 사용 되더라도, strerror_r의 n은 int를 리턴하는 POSIX 버전입니다. 그래서 그 오류가 발생한 이유를 설명합니다.

사용자에게 수동으로 #undef _GNU_SOURCE을 입력하거나 소스를 수정할 필요가 없어도 코드를 이식 가능한 상태로 유지하려면 어떻게해야합니까? _GNU_SOURCE를 전역 적으로 정의 해제하는 것은 C++ (위에서 언급 한 바와 같이 libstdC++에서 필요함)이기 때문에 시작하지 않을 가능성이 높습니다. 테스트 할 수있는 다른 매크로 조합이 있는지 알아보기 위해 노력하고 있지만 분명히 알 수있는 것은 없습니다. 당신은 C를 활용할 수

+0

공식 매크로 검사 :

char* check_error(int result, char* buffer, int err) { if(result) sprintf(buffer, "unknown error: %d", err); return buffer; } char* check_error(char* result, char*, int) { return result; } 

그리고하고는 사용에 조건부 컴파일을 제거)는'(_POSIX_C_SOURCE> = 200112L || _XOPEN_SOURCE> = 600) &&!입니다. _GNU_SOURCE'가 POSIX 버전이 제공되면 true이고, 그렇지 않으면 GNU 버전이 제공됩니다. 즉, GNU 버전이 제공되는지 확인하기에 충분해야하며 Alpine Linux의 C 라이브러리는 버그가 있거나 오래된 것으로 보입니다. –

+0

자신의 기능으로 감싸십시오. 두 가지 변형을 사용할 수있을만큼 유연하게 만듭니다. –

+0

@ n.m. 당신은 정교 할 수 있습니까? 함수에 이미 포장되어 있습니다 ... – selbie

답변

5

++ 함수를 오버로드 : (당신이 링크 매뉴얼 페이지에 따라

char buffer[1000]; 
buffer[0] = '\0'; 
char* msg = check_error(strerror_r(err, buffer, sizeof buffer), buffer, err); 
LogToFile(msg); 
+0

감사합니다. 왜 내가 이런 생각을하지 않았는지 모르겠다. 이제는 분명해 보입니다. – selbie