programing

스트렐렌의 안전한 버전이 있습니까?

codeshow 2023. 8. 15. 11:51
반응형

스트렐렌의 안전한 버전이 있습니까?

std::strlen은 \0이 종료되지 않은 c 문자열을 처리하지 않습니다.안전한 버전이 있습니까?

PS 나는 c++ std:: string이 c 문자열 대신 사용되어야 한다는 것을 알고 있지만, 이 경우 내 문자열은 공유 메모리에 저장됩니다.

편집

네, 설명을 좀 덧붙여야겠어요.

내 응용 프로그램은 공유 메모리에서 문자열을 가져오는 중이므로 문자 배열로 표시될 수 있습니다.라이브러리에서 이 문자열을 쓰는 데 버그가 있으면 문자열이 0으로 종료되지 않고 strlen이 실패할 수 있습니다.

문자열이 공유 메모리에 있음을 추가했습니다.그것은 읽기 쉽고 크기도 고정되어 있습니다.따라서 다음을 사용할 수 있습니다.size_t MaxPossibleSize = startOfSharedMemory + sizeOfSharedMemory - input; strnlen(input, MaxPossibleSize)하세요.)nstrnlen).

반됩니다가 됩니다.MaxPossibleSize\0▁▁memory▁following같에 이어지는 공유 에서.input가 있는 (최대 가능 문자열 길이는 물론MaxPossibleSize-1 가 첫 바이트인 경우\0)

Null-termined가 아닌 C 문자열은 C 문자열이 아니며 단순히 문자 배열이며 길이를 찾을 수 없습니다.

c-string을 다음과 같이 정의하는 경우

char* cowSays = "moo";

자동으로 이 그면당마자동에 '\0'이 나옵니다.strlen3 반합니다환을 반환합니다.다음과 같이 정의할 경우:

char iDoThis[1024] = {0};

빈 버퍼(및 모두 null 문자인 문자 배열)를 얻을 수 있습니다.그런 다음 버퍼 길이를 과도하게 실행하지 않는 한 원하는 값으로 채울 수 있습니다.에 음에처strlen하고, 0 반 환 할 것 이 고 을 무 당 썼 언 당 가 또 다 정 신 숫 것 입 확 얻 니 자 다 을 를 한 일 한 단 은 면 를 신 이 ▁0 ▁from ▁would ▁get ▁the ▁number 니 다 ▁correct , ▁0 ▁also▁you입▁would▁something것▁return▁and▁once을▁you환일것,이반▁written할단▁have고strlen.
다음과 같은 작업도 수행할 수 있습니다.

char uhoh[100];
int len = strlen(uhoh);

하지만 그것은 좋지 않을 것입니다. 왜냐하면 당신은 그 배열에 무엇이 있는지 모르기 때문입니다.null 문자를 입력하지 않을 수 있습니다.요점은 null 문자가 문자열이 완료되었음을 선언하는 정의된 표준 방식이라는 것입니다.
null 문자가 없다는 것은 정의상 문자열이 완료되지 않았다는 을 의미합니다.그것을 바꾸면 문자열이 어떻게 작동하는지에 대한 패러다임이 깨질 것입니다.여러분이 하고 싶은 것은 여러분만의 규칙을 만드는 것입니다.C++는 당신이 그렇게 할 수 있도록 해줄 것이지만, 당신이 직접 많은 코드를 작성해야 할 것입니다.

편집 새로 추가된 정보에서 어레이를 루프하고 null 문자를 손으로 확인합니다.ASCII 문자만 사용하는 경우(특히 영숫자 문자를 사용하는 경우)에도 일부 검증을 수행해야 합니다.이 경우 최대 크기를 알고 있다고 가정합니다.문자열 내용의 유효성을 검사할 필요가 없는 경우 다음 중 하나를 사용할 수 있습니다.strnlen함수 계열: http://msdn.microsoft.com/en-us/library/z50ty2zh%28v=vs.80%29.aspx
http://linux.about.com/library/cmd/.htmhttp ://linux.about.com/library/cmd/blcmdl3_strnlen.htm

size_t safe_strlen(const char *str, size_t max_len)
{
    const char * end = (const char *)memchr(str, '\0', max_len);
    if (end == NULL)
        return max_len;
    else
        return end - str;
}

예, C11 이후:

size_t strnlen_s( const char *str, size_t strsz );

위치

더 나은 라이브러리를 얻거나 보유한 라이브러리를 확인하십시오. 라이브러리가 원하는 대로 실행할 수 없다면 프로그램이 어떻게 실행될 것으로 예상하십니까?

즉, 만약 당신이 끈이 존재하는 부이퍼의 길이를 알고 있다고 가정하면,

buffer[-1+sizeof(buffer)]=0 ;
 x = strlen(buffer) ; 
  • 버퍼를 필요 이상으로 크게 만들면 lib를 테스트할 수 있습니다.

    assert(x<-1+sizeof(buffer));
    

은 C11과 같은 "포함하고 .strnlen_s.strnlen_s합니다(" 추가최길사다니합용인를수이대a(다(a)).size_t). 많은 한 후 수 이 가 반환됩니다 해당 문자를 확인한 후 null 문자를 찾지 못하면 이 인수가 반환됩니다.또한 null 포인터가 제공된 경우 두 번째 인수를 반환합니다.

size_t strnlen_s(const char *, size_t);

가 C11의 경계 검사 ".__STDC_LIB_EXT1__또한사는매다설합니다정야해도 해야 합니다.__STDC_WANT_LIB_EXT1__로, 그리고.1포하기전에함을 포함하기 string.h그들이 그러한 기능을 사용할 수 있습니다.이러한 함수의 기원에 대한 스택 오버플로 설명은 여기를 참조하고 C++ 설명서는 여기를 참조하십시오.

함수 GCC, Clang, POSIX를 합니다.strnlen그리고 그것을 제공합니다.string.h도 »strnlen이는 또한 안에서 찾을 수 있습니다.string.h.

문자열을 인코딩해야 합니다.예:

struct string
{
    size_t len;
    char *data;
} __attribute__(packed);

공유 메모리 위치의 첫 번째 크기(size_t) 바이트가 문자 배열의 크기라는 것을 알고 있는 경우 문자 배열을 사용할 수 있습니다.이러한 방식으로 어레이를 체인으로 연결하려면 까다로워집니다.

다른 쪽 끝을 신뢰하여 문자열을 종료하거나 공유 메모리 세그먼트의 경계 밖으로 나가지 않는 자신의 스트렐렌을 롤링하는 것이 좋습니다(최소한 해당 세그먼트의 크기를 알고 있다면).

공유 메모리의 크기를 가져와야 하는 경우

// get memory size
struct shmid_ds shm_info;
size_t shm_size;
int shm_rc;
if((shm_rc = shmctl(shmid, IPC_STAT, &shm_info)) < 0)
    exit(101);
shm_size = shm_info.shm_segsz;

shm_size - 1이 null로 종료된 것이 확실한 경우 strlen을 사용하는 대신 사용할 수 있습니다.그렇지 않으면 null을 데이터 [shm_size - 1] = '\0'으로 종료한 다음 strlen(data)을 사용할 수 있습니다.

간단한 해결책:

buff[BUFF_SIZE -1] = '\0'

이것은 문자열이 원래 정확히 BUFF_SIZE-1인지 아니면 단지 종료되지 않았는지 알려주지 않을 것입니다...그래서 당신은 그것을 위한 추가 논리가 필요합니다.

이 휴대용 너겟은 어떻습니까?

int safeStrlen(char *buf, int max)
{
   int i;
   for(i=0;buf[i] && i<max; i++){};
   return i;
}

버터워스가 위의 답변에서 이미 말했듯이: \0 문자로 끝나지 않는 C-Strings는 C-Strings가 아닙니다!

당신이 가질 수 있는 유일한 기회는 불변의 어댑터 또는 \0 끝 문자로 유효한 C-String 복사본을 만드는 것입니다.물론 입력이 잘못되고 다음과 같이 정의된 C-String이 있는 경우:

char cstring[3] = {'1','2','3'};

실제로 예상치 못한 행동을 초래할 것입니다, 왜냐하면 비슷한 것이 있을 수 있기 때문입니다.123@4x\0를 들어 strlen입니다.따라서 예를 들어 strlen()의 결과는 예상대로 3이 아니라 6입니다.

다음 접근 방식은 어떤 경우에도 안전한 C-String을 만드는 방법을 보여줍니다.

char *createSafeCString(char cStringToCheck[]) {
    //Cast size_t to integer
    int size = static_cast<int>(strlen(cStringToCheck)) ;
    //Initialize new array out of the stack of the method
    char *pszCString = new char[size + 1];
    //Copy data from one char array to the new
    strncpy(pszCString, cStringToCheck, size);
    //set last character to the \0 termination character
    pszCString[size] = '\0';
    return pszCString;
}

이렇게 하면 C-String을 조작하여 다른 메모리에 쓰지 않도록 할 수 있습니다.

하지만 이것은 당신이 원했던 것이 아닙니다.알아요, 하지만 종료 없이 문자 배열의 길이를 달성할 수 있는 다른 방법은 없어요.이건 접근법도 아닙니다.사용자(또는 개발자)가 *****를 삽입하여 정상적으로 작동하는 경우에도 이 기능을 사용할 수 있습니다.

언급URL : https://stackoverflow.com/questions/5935413/is-there-a-safe-version-of-strlen

반응형