programing

왜 공포증을 사용할 수 없습니까?

cafebook 2023. 7. 22. 10:24
반응형

왜 공포증을 사용할 수 없습니까?

컴파일러 C 8에서 Windows의 Microsoft 버전(Visual C++ 8)을 .strerror()안전하지 않습니다.

마이크로소프트의 모든 안전 끈에 있는 성가신 요소는 제쳐두고, 저는 실제로 몇몇 사용되지 않는 기능들이 위험하다는 것을 알 수 있습니다.하지만 뭐가 문제인지 이해할 수 없습니다.strerror()코드가필니다합요다니▁(▁a코)를 합니다.int를 선택하고 문자열을 합니다. 알 수 없는 빈 을 반환합니다을 클릭하고 해당 문자열을 반환합니다. 또는 해당 코드를 알 수 없는 경우 빈 문자열을 반환합니다.

어디에 위험이 있습니까?

C에 좋은 대안이 있습니까?

C++에 좋은 대안이 있습니까?

[편집]

몇 가지 좋은 답변을 얻었고, 이제 일부 구현은 공통 공유 버퍼에 실제로 쓸 수 있을 정도로 충분히 미친 것일 수 있다는 것을 알게 되었습니다. 단일 스레드 내에서 재가입하는 것은 안전하지 않습니다. 스레드 간에 상관하지 마십시오. 제 질문은 "왜 사용할 수 없고 대체 방법은 무엇입니까?"라는 것입니다.C 및/또는 C++의 간결한 대안?"

잘 부탁드립니다.

strerror스레드 세이프가 아니기 때문에 더 이상 사용하지 않습니다.strerror다른 동시 스레드에 의해 덮어쓸 수 있는 내부 정적 버퍼에서 작동합니다.여러분은 다과같은보사합니용다야해형을변라는 .strerror_s.

보안 변형에서는 버퍼 크기가 함수에 전달되어야 버퍼 크기가 충분히 큰지 확인할 수 있으므로 악의적인 코드가 실행될 수 있는 버퍼 오버런을 방지할 수 있습니다.

strerror그 자체로는 안전하지 않습니다.스레드화하기 전의 옛날에는 단순히 문제가 되지 않았습니다.스레드를 사용할 경우 두 개 이상의 스레드가 호출할 수 있습니다.strerror반환된 버퍼를 정의되지 않은 상태로 둡니다.단일 스레드 프로그램의 경우 사용해도 문제가 없습니다.strerrorDLL의 모든 앱에 대한 공통 메모리와 같이 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

반응형