programing

길이 프리픽스 문자열이 극복하는 제로 터미네이션 문자열의 문제점은 무엇입니까?

topblog 2023. 9. 15. 20:40
반응형

길이 프리픽스 문자열이 극복하는 제로 터미네이션 문자열의 문제점은 무엇입니까?

길이 프리픽스 문자열이 극복하는 제로 터미네이션 문자열의 문제점은 무엇입니까?

저는 '위대한 코드를 써라' 1권을 읽다가 그 질문을 받았습니다.

한 가지 문제는 제로 종료 문자열에서는 문자열의 끝을 반복적으로 찾아야 한다는 것입니다.이것이 비효율적인 전형적인 예는 버퍼에 연결되는 것입니다.

char buf[1024] = "first";
strcat(buf, "second");
strcat(buf, "third");
strcat(buf, "fourth");

strcat프로그램은 문자열의 처음부터 시작해서 어디부터 추가해야 할지 알기 위해 터미네이터를 찾아야 합니다.이는 문자열이 길어질수록 함수가 추가할 위치를 찾는 데 점점 더 많은 시간을 소비한다는 것을 의미합니다.

가 은 과 된 과 에 해당하는 길이의 을 사용합니다.strcat함수는 엔드가 어디에 있는지 바로 알 수 있고, 엔드에 추가한 후에 길이만 업데이트 할 것입니다.

문자열을 표현하는 각 방법에는 장단점이 있으며 문자열을 사용하여 무엇을 수행하는지, 어떤 작업이 효율적이어야 하는지에 따라 문제가 발생하는지 여부가 달라집니다.상기와 같은 문제점은 스트링의 끝단이 커짐에 따라 수동으로 추적함으로써 극복할 수 있으므로, 코드를 변경함으로써 성능 비용을 회피할 수 있습니다.

한 가지 문제는 0의 종료 문자열에 null 문자(값 0)를 저장할 수 없다는 것입니다.따라서 암호화된 데이터뿐만 아니라 일부 문자 인코딩을 저장할 수 없습니다.

길이 접두사 문자열은 이러한 제한을 받지 않습니다.

먼저 설명:C++ 문자열(즉, C++ 문자열)std::string ) 아녜요 C++11까지 0으로 끝날 필요가 없었습니다.그들은 항상 제로 종단 C 문자열에 대한 액세스를 제공했습니다.

C 스타일 문자열은 기록상의 이유로 0자로 끝납니다.

사용자가 언급하는 문제는 주로 보안 문제와 관련이 있습니다. 제로 엔드 문자열은 제로 터미네이터가 있어야 합니다.어떤 이유로든 문자열이 부족하면 문자열의 길이를 신뢰할 수 없게 되고 버퍼 오버런 문제가 발생할 수 있습니다(악의적인 공격자는 임의의 데이터를 사용해서는 안 되는 곳에 악용할 수 있습니다).DEP는 이러한 문제를 완화하는 데 도움이 되지만 여기서는 주제가 다릅니다.

폴헤닝 캠프의 가장 비싼 1바이트 실수로 가장 잘 요약됩니다.

  1. 성능 비용:항상 NULL 문자를 찾아야 한다면 할 수 없는 청크로 메모리를 조작하는 것이 더 저렴합니다.즉, 129개의 문자열을 가지고 있다는 것을 미리 알고 있다면 문자별로 입력하는 대신 64, 64, 1바이트 구간으로 조작하는 것이 더 효율적일 것입니다.
  2. 보안:마르코 A는 이미 꽤 세게 때렸습니다.문자열 버퍼 오버 및 언더 실행은 여전히 해커의 공격에 대한 주요 경로입니다.

  3. 컴파일러 개발 비용: 큰 비용은 주소와 길이 형식으로 더 쉬웠을 널 터미네이션 문자열에 대한 컴파일러 최적화와 관련이 있습니다.

  4. 하드웨어 개발 비용: Null 종단 문자열과 관련된 문자열 특정 명령의 경우에도 하드웨어 개발 비용이 큽니다.

길이 접두사 문자열로 구현할 수 있는 몇 가지 추가 기능:

  1. 문자열 포인터/참조로 식별되는 첫 번째 바이트의 하나 이상의 비트를 통해 식별 가능한 여러 스타일의 길이 접두사를 가질 수 있습니다.문자열 길이를 결정하는 데 약간의 추가 시간을 할애하는 대신 짧은 문자열에는 단일 바이트 접두사를 사용하고 긴 문자열에는 긴 접두사를 사용할 수 있습니다.고정된 4바이트 접두사를 사용하는 것에 비해 이러한 문자열의 전체 메모리 사용량을 50% 이상 절약할 수 있는 1-3바이트 문자열을 많이 사용하는 경우, 이러한 형식은 길이가 32비트 정수 범위를 초과하는 문자열도 수용할 수 있습니다.

  2. 하나는 길이 접두어에 단지 1비트 또는 2비트의 비용으로 경계 검사 버퍼 내에 가변 길이 문자열을 저장할 수 있습니다.다른 비트와 결합된 숫자 N은 다음 세 가지 중 하나를 나타냅니다.

    1. N바이트 문자열

    2. (선택사항) 0-길이 문자열을 포함하는 N-바이트

    3. 마지막 바이트 B가 248보다 작으면 N-B-1 길이의 문자열을 보유하고, 248 이상이면 이전의 B-247 바이트가 버퍼 크기와 문자열 길이의 차이를 저장합니다.문자열의 길이가 정확히 N-1이면 문자열 뒤에 NUL 바이트가 있고, 문자열 뒤에 오는 바이트가 사용되지 않고 NUL로 설정될 수 있습니다.

    이러한 접근 방식을 사용하면 사용하기 전에 강력한 버퍼를 초기화해야 하지만(그 길이를 나타내기 위해), 더 이상 문자열 버퍼의 길이를 데이터를 저장하는 루틴에 전달할 필요가 없습니다.

  3. 어떤 사람은 다양한 특별한 것들을 나타내기 위해 특정한 접두사 값을 사용할 수 있습니다.예를 들어, 하나는 문자열 뒤에 오는 것이 아니라 문자열-데이터 포인터와 버퍼 크기 및 현재 길이를 나타내는 두 개의 정수를 나타내는 접두사를 가질 수 있습니다.문자열에서 동작하는 메서드가 데이터 포인터, 버퍼 크기 및 길이를 얻기 위해 메서드를 호출하는 경우 문자열 자체가 메서드 호출보다 오래 지속되는 경우 문자열의 일부를 저렴하게 참조할 수 있습니다.

  4. 문자열 데이터가 다음에 의해 생성된 영역에 있음을 나타내기 위해 비트와 함께 위의 특징을 확장할 수 있습니다.malloc필요에 따라 크기를 조정할 수도 있으며, 때로는 힙에 할당된 동적 생성 문자열을 반환하고 때로는 불변 정적 문자열을 반환하는 방법을 안전하게 사용할 수 있으며, 수신자가 "정적이 아니면 이 문자열을 해제"하도록 할 수도 있습니다.

프리픽스 문자열 구현이 이러한 모든 보너스 기능을 구현하는지는 모르겠지만, 이 모든 기능을 스토리지 공간에서 매우 적은 비용, 코드 비용, 길이가 알려지지도 짧지도 않은 NUL 종단 문자열을 사용하는 데 필요한 비용보다 시간적인 비용으로 수용할 수 있습니다.

길이 프리픽스 문자열이 극복하는 제로 터미네이션 문자열의 문제점은 무엇입니까?

전혀 아닙니다.
그냥 눈사탕.

길이로 접두사가 붙은 문자열은 문자열의 길이에 대한 정보를 구조의 일부로 가지고 있습니다.0-종료 문자열을 사용하여 동일한 작업을 수행하려면 도우미 변수를 사용할 수 있습니다.

lpstring = "foobar"; // saves '6' somewhere "inside" lpstring

ztstring = "foobar";
ztlength = 6;        // saves '6' in a helper variable

많은 C 라이브러리 함수들은 제로 종료 문자열들과 함께 작동하고 다음의 어떤 것도 사용할 수 없습니다.'\0'바이트. 그건 문자열 구조가 아니라 함수 자체의 문제입니다.0이 포함된 제로 종료 문자열을 처리하는 함수가 필요하다면 자신의 함수를 작성합니다.

언급URL : https://stackoverflow.com/questions/30458433/what-are-the-problems-of-a-zero-terminated-string-that-length-prefixed-strings-o

반응형