2010-06-16 2 views
9

GNU 버전 대신 POSIX strerror_r을 얻으려면 어떻게해야합니까?GNU 버전 대신 POSIX strerror_r을 얻는 방법은 무엇입니까?

glibc 버전 2.7 (무엇을 기반으로하는지)로 우분투 8.04에서 g ++로 컴파일 중입니다.

는 말한다 위의 사람 페이지에서 편집

: glibc에 대한

기능 테스트 매크로 요구 사항 (참조 feature_test_macros (7)) :

The XSI-compliant version of strerror_r() is provided if: 
    (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE 
    Otherwise, the GNU-specific version is provided. 

그런 다음 feature_test_macros(7) 말한다 :

If no feature test macros are explicitly defined, then the following feature 
    test macros are defined by default: _BSD_SOURCE, _SVID_SOURCE, _POSIX_SOURCE, 
    and _POSIX_C_SOURCE=200809L (200112L in glibc versions before 2.10; 199506L in 
    glibc versions before 2.4; 199309L in glibc versions before 2.1). 

그래서 POSIX 버전을 가져야합니다. 대신 GNU를 얻고 있습니다. 헤더 string.h에서

+1

헤더 파일이나 파티 헤더가 없습니다. '_GNU_SOURCE'? – nos

답변

7

: GNU 확장을 사용하는 경우

/* Reentrant version of `strerror'. 
    There are 2 flavors of `strerror_r', GNU which returns the string 
    and may or may not use the supplied temporary buffer and POSIX one 
    which fills the string into the buffer. 
    To use the POSIX version, -D_XOPEN_SOURCE=600 or -D_POSIX_C_SOURCE=200112L 
    without -D_GNU_SOURCE is needed, otherwise the GNU version is 
    preferred. */ 

주에 그들을 설정,주의 (_GNU_SOURCE) 마지막으로, 당신이 영향 (또는 전략적으로 그것을 정의를 해제) 할 헤더를 포함하기 전에. GNU 확장을 사용하지 않는다고해도 걱정할 필요가 없습니다.

일반적으로 GNU가 기본 동작에서 POSIX를 벗어나면 헤더에 몇 가지 주석이 표시되어 POSIX 동작을 얻는 방법을 나타냅니다. 그것도 (일반적으로) glibc 매뉴얼에 문서화되어 있지만, 그것이 항상 압축 된 man 페이지를 만드는 것은 아니다.

편집

이 간단한 테스트를 시도 : 뭔가 다른 발생하지 않는 한

#include <string.h> 
#ifdef _GNU_SOURCE 
#error "Something turned it on!" 
#endif 

또는 정의 _POSIX_C_SOURCE={version}하면 더 직접적으로

#ifdef _GNU_SOURCE 
#undef _GNU_SOURCE 
#endif 
#include <string.h> 

을, 당신은은 POSIX 버전이 있어야합니다 GNU 버전이 선호됩니다.

내가 할 수있는 유일한 생각은 _GNU_SOURCE입니다. 나는 이것이 당신의 커맨드 라인 플래그에 없다고 확신합니다, 당신은 그것을 보았을 것입니다. 포함 된 또 다른 라이브러리가 켜져있을 수 있습니다.

그게 내가 POSIX 구현을 선호한다고 요청할 때 확장 기능이 '까다로운'것이라는 의미였습니다.

뭔가 (부스트가하는 아닌지 내가 ++ 나 C를 할만큼 많은 C를 사용하지 않는, 회수 할 수 없습니다) _GNU_SOURCE 켠 경우, 당신은 아마 그것을 허용 할 편집 그렇게하려면. 명령 행에서 --undef "[macro]" -U[macro]을 사용할 수 있습니다.그러나,이 라이브러리 코드는 다음과 같은 경우에 작동하지 않습니다

#ifndef _GNU_SOURCE 
#define _GNU_SOURCE 
#endif 

#include <stdio.h> 
#include <string.h> 

#ifdef _GNU_SOURCE 
#error "It didn't work" 
#endif 

int main(void) 
{ 
    return 0; 
} 

문제는이다, 코드가 실제로 string.h 포함하는 시간, 뭔가 다른 이미 확장 켜져 있고 그것을 포함하고있다. 경비원을 포함 시키면 당연히 두 번 포함시키지 못하게됩니다.

명시 적으로 _GNU_SOURCE을 끄고 보다 먼저 string.h을 포함하면 이외의 문자를 사용해보십시오. 이렇게하면 다른 라이브러리에서 해당 확장을 사용하지 못하게 할 수 있습니다. 그러나 이러한 라이브러리가 없으면 라이브러리가 작동하지 않을 수 있습니다. 일부 코드는 GNU의 동작을 '예상'하며 POSIX에 대한 대체를 포함하지 않습니다.

나는 asprintf() 없이는 작동하지 않는 라이브러리 코드와 비슷한 불만을 경험했습니다.

+0

필자가 이해할 수없는 것은 문서에서'_POSIX_C_SOURCE = 200112L'이 기본적으로 정의되어 있습니다 (OP에 편집 참조). 그래서 왜 GNU 버전을 얻고 있는지 이해할 수 없습니다. –

+0

나는 첫 번째 것을 시도하고, 명백하게 무언가가 그것을 켜고있다. 내 코드에서 아무 것도 켜져 있지 않으므로 glibc, stdlib ++ (STL) 또는 Boost로 가정해야합니다. 커맨드 라인에서 전역 적으로 undef하는 방법이 있습니까? –

+0

@ 로버트 - glibc/stdlib ++가 기본적으로 확장 기능을 사용한다고 생각하지 않습니다. 그것은 아마 부스트, 또는 다른 라이브러리에서 오는. 문자열 헤더가'-D_POSIX_C_SOURCE'와 함께 처음으로 (boost 전에) 포함되면, 그것은 _off_가되어야합니다. 내 편집을 참조하십시오. –

1

표준에 의해 스레드로부터 안전 할 필요는 없지만 정상적인 사람이 스레드로부터 안전하지 않은 strerror을 작성할 수있는 방법은 상상할 수 없습니다. 사람들은 무엇을합니까? gunzip 런타임시 오류 문자열 또는 무엇인가?! 좋은 strerror은 표준 라이브러리의 문자열 상수 나 로케일 메시지 파일의 상수 mmap '메모리로 포인터를 리턴해야합니다.

사과하지 않겠지 만 절대적인 이론적 인 이식성에 대해 신경 쓰지 않는다면 관심있는 모든 구현에 정상적인 strerror 동작이 있는지 확인하고 확인할 수 있습니다. .

+1

너 재미있어. 그 두 번째 문장은 내가 LOL'ing했다. 와우, 나는 단지 LOL'ing이라고 타이핑했다는 것을 믿을 수 없다. 너는 내가 그런 13 개의 타이핑 물건이라고 생각할 것이다.Bahh, 아마도 너무 많은 맥주와 너무 많은 단위 테스트를 하룻밤. –

+2

어리석은'_r' 변형의 또 다른 함수는'readdir'입니다. 버퍼를 포함하는 완벽하게 좋은'DIR' 구조체 (또는 여러개의 스레드로부터 하나의'DIR '을 정말로 고집하는 경우에 동적으로 할당되는 쓰레드 버퍼에 대한 포인터)와'readdir_r'을 추가하는 것은 절대적으로 필요하지 않습니다 (clunky 인터페이스). –

+0

맨 페이지에는 "unknown error NNN"예제가 나열됩니다. 그리고 그것은 번역이 없습니다. – o11c

1

구현 별 해결 방법입니다.

#ifdef __cplusplus 
extern "C" 
    { 
#endif 
    extern 
    int __xpg_strerror_r(int errcode,char* buffer,size_t length); 
    #define strerror_r __xpg_strerror_r 

#ifdef __cplusplus 
    } 
#endif 
+0

우리가 유저 랜드를 말할 때 왜 커널 버전을 제공합니까? –

관련 문제