왜 공포증을 사용할 수 없습니까?
컴파일러 C 8에서 Windows의 Microsoft 버전(Visual C++ 8)을 .strerror()
안전하지 않습니다.
마이크로소프트의 모든 안전 끈에 있는 성가신 요소는 제쳐두고, 저는 실제로 몇몇 사용되지 않는 기능들이 위험하다는 것을 알 수 있습니다.하지만 뭐가 문제인지 이해할 수 없습니다.strerror()
코드가필니다합요다니▁(▁a코)를 합니다.int
를 선택하고 문자열을 합니다. 알 수 없는 빈 을 반환합니다을 클릭하고 해당 문자열을 반환합니다. 또는 해당 코드를 알 수 없는 경우 빈 문자열을 반환합니다.
어디에 위험이 있습니까?
C에 좋은 대안이 있습니까?
C++에 좋은 대안이 있습니까?
[편집]
몇 가지 좋은 답변을 얻었고, 이제 일부 구현은 공통 공유 버퍼에 실제로 쓸 수 있을 정도로 충분히 미친 것일 수 있다는 것을 알게 되었습니다. 단일 스레드 내에서 재가입하는 것은 안전하지 않습니다. 스레드 간에 상관하지 마십시오. 제 질문은 "왜 사용할 수 없고 대체 방법은 무엇입니까?"라는 것입니다.C 및/또는 C++의 간결한 대안?"
잘 부탁드립니다.
strerror
스레드 세이프가 아니기 때문에 더 이상 사용하지 않습니다.strerror
다른 동시 스레드에 의해 덮어쓸 수 있는 내부 정적 버퍼에서 작동합니다.여러분은 다과같은보사합니용다야해형을변라는 .strerror_s
.
보안 변형에서는 버퍼 크기가 함수에 전달되어야 버퍼 크기가 충분히 큰지 확인할 수 있으므로 악의적인 코드가 실행될 수 있는 버퍼 오버런을 방지할 수 있습니다.
strerror
그 자체로는 안전하지 않습니다.스레드화하기 전의 옛날에는 단순히 문제가 되지 않았습니다.스레드를 사용할 경우 두 개 이상의 스레드가 호출할 수 있습니다.strerror
반환된 버퍼를 정의되지 않은 상태로 둡니다.단일 스레드 프로그램의 경우 사용해도 문제가 없습니다.strerror
DLL의 모든 앱에 대한 공통 메모리와 같이 libc에서 이상한 게임을 하는 경우가 아니라면요.
이 문제를 해결하기 위해 동일한 기능에 대한 새로운 인터페이스가 있습니다.
int strerror_r(int errnum, char *buf, size_t buflen);
호출자는 버퍼 공간과 버퍼 크기를 제공합니다.이렇게 하면 문제가 해결됩니다.단일 스레드 애플리케이션의 경우에도 사용하는 것이 좋습니다.그것은 조금도 아프지 않을 것이고, 당신은 그것을 안전한 방법으로 하는 것에 익숙해지는 것이 좋을 것입니다.
참고: 위의 프로토타입은 의 POSIX 사양에서 가져온 것입니다.플랫폼마다 또는 컴파일러 옵션에 따라 다를 수 있습니다.#define
기호예를 들어, GNU는 그것이나 그들만의 버전을 사용할 수 있게 합니다.#define
.
몇 가지 좋은 답변을 얻었고, 이제 일부 구현은 공통 공유 버퍼에 실제로 쓸 수 있을 정도로 충분히 미친 것일 수 있다는 것을 알게 되었습니다. 단일 스레드 내에서 재가입하는 것은 안전하지 않습니다. 스레드 간에 상관하지 마십시오. 제 질문은 "왜 사용할 수 없고 대체 방법은 무엇입니까?"라는 것입니다.C 및/또는 C++의 간결한 대안?"
는 Posix를 지정합니다.strerror_r()
(윈도우)에서는(윈도우)를 사용할 수 .strerror_s()
조금 다르지만 같은 목표를 가지고 있는 것.사용자 작업을 수행합니다.
#define BAS_PERROR(msg, err_code)\
bas_perror(msg, err_code, __FILE__, __LINE__)
void bas_perror (const char* msg, int err_code, const char* filename,
unsigned long line_number);
void
bas_perror (const char* usr_msg, int err_code, const char* filename,
unsigned long line_number)
{
char sys_msg[64];
#ifdef _WIN32
if ( strerror_s(sys_msg, sizeof sys_msg, err_code) != 0 )
{
strncpy(sys_msg, "Unknown error", taille);
sys_msg[sizeof sys_msg - 1] = '\0';
}
#else
if ( strerror_r(err_code, sys_msg, sizeof sys_msg) != 0 )
{
strncpy(sys_msg, "Unknown error", sizeof sys_msg);
sys_msg[sizeof sys_msg - 1] = '\0';
}
#endif
fprintf(stderr, "%s: %s (debug information: file %s, at line %lu)\n",
usr_msg, sys_msg, filename, line_number);
}
Posix 스레드 함수가 수정되지 않기 때문에 이 함수를 작성했습니다.errno
대신 오류 코드를 반환합니다.따라서 이 기능은 기본적으로 다음과 같습니다.perror()
다음 이외의 오류 코드를 제공할 수 있다는 점을 제외하고는errno
및 일부 디버깅 정보도 표시합니다.필요에 따라 조정할 수 있습니다.
에서 반환된 문자열에 의존할 수 없습니다.strerror()
함수에 대한 다음 호출과 함께 변경될 수 있기 때문입니다.그러면 이전에 반환된 값이 더 이상 사용되지 않을 수 있습니다.특히 멀티스레드 환경에서는 문자열에 액세스할 때 문자열이 유효한지 확인할 수 없습니다.
상상해 보십시오.
Thread #1:
char * error = strerror(1);
Thread #2
char * error = strerror(2);
printf(error);
의 strerror()
2에 를 출력합니다. 에러 코드 1. 에러 코드 2. 에러 코드 2를 출력합니다.
간단한 포장지의 경우 STL Soft의stlsoft::error_desc
다음과 같이:
std::string errstr = stlsoft::error_desc(errno);
코드를 보면, 그것은 다음과 같은 측면에서 구현된 것 같습니다.strerror()
즉, 스레드 내에서 재진입(즉, 지정된 문 내에서 여러 번 사용되는 경우)에 안전하지만 멀티스레딩 문제는 해결되지 않습니다.
결함에 대한 릴리스 주기가 상당히 빠른 것 같은데 모드를 요청해보시겠어요?
다른 답변은 이해하지만 코드로 보여주는 것이 더 명확하다고 생각합니다.
glibc의 구현을 확인합니다(MS lib에서 유사한 코드를 얻어야 합니다).
/* Return a string describing the errno code in ERRNUM.
The storage is good only until the next call to strerror.
Writing to the storage causes undefined behavior. */
libc_freeres_ptr (static char *buf);
때.errnum
알 수 없는 오류가 아니라 "알 수 없는 오류 41"과 같은 문자열을 생성해야 합니다.이 문자열은 상수가 아니지만 할당된 버퍼에 생성됩니다. 리고그.buf
var 때문에 시 이 변경될 수 .strerror
다시 자물쇠를 채웁니다.그래서 나사산이 안전하지 않습니다.
에반면은,strerror_r(int errnum, char *buf, size_t buflen)
인수에 대한 오류 문자열을 생성합니다.buf
그래서 지금은 글로벌 자원이 없습니다.그래서 스레드 세이프입니다.
참조: https://github.com/liuyang1/glibc/blob/master/string/strerror.c#L23-L26
이 함수의 사양은 스레드 안전 분야에서 다소 부족합니다.예: 맨스트레일러(3):
이 문자열은 응용 프로그램에서 수정할 수 없지만 이후에 strerror()를 호출하면 수정할 수 있습니다.
그러나 Windows API 및 GLIBC 버전의 오류는 스레드 로컬 스토리지를 사용하므로 사용하기에 완벽하게 안전합니다.
마이크로소프트의 이유는 모르지만, 스트러가 비콘스탄트 *를 반환한다는 점에 주목합니다. 이는 사용자가 메시지를 수정하기 전에 어떤 메리 장난꾼이 스트러를 호출하고 수정했을 위험이 있다는 것을 의미합니다.
언급URL : https://stackoverflow.com/questions/900338/why-cant-i-use-strerror
'programing' 카테고리의 다른 글
SpringFox Swagger - 모델의 옵션 및 필수 필드 (0) | 2023.07.22 |
---|---|
스프링 부트 3의 스프링 보안 (0) | 2023.07.22 |
교육을 받은 Keras 모델 로드 및 교육 계속 (0) | 2023.07.22 |
Oracle DataReader를 통해 읽을 때 NULL 값을 처리하시겠습니까? (0) | 2023.07.22 |
Visual Studio Code에서 긴 줄 자동 줄 바꿈 사용 안 함 (0) | 2023.07.22 |