널 종단 문자열
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
널 종단 문자열은 문자열의 끝을 나타내기 위해 널 문자(NUL, ASCII 코드 0)를 사용하는 문자열 표현 방식이다. C 언어에서 기본 문자열 형식으로 채택되었으며, 1970년대 PDP-11 어셈블리 언어에서 처음 사용되었다. 메모리 사용량 절감이라는 장점이 있었지만, 버퍼 오버플로우와 같은 보안 문제와 성능 저하를 야기하기도 했다. 이러한 문제점을 해결하기 위해 C++의 `std::string`, Qt의 `QString`과 같은 객체 지향 래퍼를 사용한 개선된 문자열 처리 방식이 개발되었다.
더 읽어볼만한 페이지
- 문자열 자료 구조 - LCP 배열
LCP 배열은 문자열 처리 알고리즘에서 접미사 배열 내 인접한 두 접미사의 최장 공통 접두사 길이를 저장하는 자료구조로, 문자열 검색 시간 향상에 기여하며, 카사이 알고리즘 등으로 선형 시간 내 계산이 가능하고, 패턴 발생 횟수 찾기 등 다양한 문자열 문제 해결에 활용됩니다. - 문자열 자료 구조 - 접미사 배열
접미사 배열은 문자열의 모든 접미사를 사전 순으로 정렬했을 때 각 접미사의 시작 위치를 담은 배열로, 문자열 처리, 생물 정보학, 데이터 압축 등 다양한 분야에서 활용되며, 비교 정렬, Manber-Myers 알고리즘, SA-IS 알고리즘 등을 통해 구축된다. - 자료 구조 - 라우팅 테이블
라우팅 테이블은 네트워크에서 데이터 전송 시 최적 경로를 결정하는 핵심 데이터베이스로, 라우터가 목적지 IP 주소를 기반으로 다음 홉을 결정하며 직접 연결 및 원격 네트워크 경로 정보를 저장하고 동적 라우팅 또는 수동 설정으로 관리된다. - 자료 구조 - 스택
스택은 후입선출(LIFO) 원칙에 따라 데이터를 관리하는 추상 자료형으로, push 연산으로 데이터를 쌓고 pop 연산으로 가장 최근 데이터를 제거하며, 서브루틴 호출 관리, 수식 평가, 백트래킹 등에 활용된다.
널 종단 문자열 |
---|
2. 역사
널 종단 문자열은 PDP-11 어셈블리 언어의 `.ASCIZ` 지시어와 PDP-10의 MACRO-10 매크로 어셈블리 언어의 `ASCIZ` 지시어에서 유래되었다. 이는 C 프로그래밍 언어 개발보다 앞선 시점이었다.[2]
2. 1. C 언어에서의 채택
C 언어가 개발될 당시 메모리가 극도로 제한적이었기 때문에, 문자열 길이를 저장하기 위해 추가적인 바이트를 사용하지 않는 널 종단 방식이 채택되었다. 데니스 리치는 문자열의 길이를 별도로 저장하는 방식(파스칼 문자열) 대신 널 종단 방식을 선택했는데, 이는 문자열 길이 제한을 피하고, 그의 경험상 개수를 유지하는 것보다 널 종단자를 사용하는 것이 더 편리하다고 판단했기 때문이다.[2][3]이러한 결정은 CPU 명령어 집합 설계에도 영향을 미쳤다. 1970년대와 1980년대의 자일로그 Z80, DEC VAX와 같은 일부 CPU는 길이 접두사 문자열 처리를 위한 전용 명령을 가지고 있었다. 그러나 널 종단 문자열이 널리 사용되면서, CPU 설계자들은 이를 고려하기 시작했다. 예를 들어, IBM은 1992년 ES/9000 520에 "논리 문자열 지원" 명령을 추가했고, 2015년 IBM z13에는 벡터 문자열 명령을 추가했다.[4]
FreeBSD 개발자 폴-헤닝 캄프는 ''ACM 큐''에서 널 종단 문자열이 2바이트(1바이트가 아닌) 길이에 대한 승리를 "가장 비싼 1바이트 실수"라고 언급했다.[5]
2. 2. CPU 명령어 집합에 미친 영향
CPU 명령어 집합 설계에 어느 정도 영향을 미쳤다. 1970년대와 1980년대의 Zilog Z80 및 DEC VAX와 같은 일부 CPU는 길이 접두사 문자열을 처리하기 위한 전용 명령을 가지고 있었다. 그러나 널 종단 문자열이 인기를 얻으면서, CPU 설계자들은 이를 고려하기 시작했다. 예를 들어 IBM은 1992년 ES/9000 520에 "논리 문자열 지원" 명령을 추가하고, 2015년 IBM z13에 벡터 문자열 명령을 추가하는 등 널 종단 문자열 처리를 위한 하드웨어 지원을 강화했다.[4]FreeBSD 개발자 폴-헤닝 캄프는 ''ACM 큐''에 기고하면서 널 종단 문자열이 2바이트(1바이트가 아닌) 길이에 대한 승리를 "가장 비싼 1바이트 실수"라고 언급했다.[5]
3. 구현
C 프로그래밍 언어는 널 종단 문자열을 기본 문자열 형식으로 지원한다.[24][15] C 표준 라이브러리는 널 종단 문자열 처리를 위한 다양한 함수들을 제공한다. 이러한 함수들은 다음과 같은 기능을 포함한다:
- 문자열 길이 결정
- 한 문자열을 다른 문자열로 복사
- 한 문자열을 다른 문자열 뒤에 추가
- 문자열 내 특정 문자의 처음 또는 마지막 발생 부분 찾기
- 주어진 집합에 포함되거나 포함되지 않는 문자의 첫 발생 부분을 문자열 내에서 찾기
- 문자열 내의 서브스트링의 첫 발생 부분을 찾기
- 두 문자열을 사전적으로 비교하기
- 문자열을 여러 서브스트링으로 나누기
- 숫자값 또는 문자값을 인쇄 가능한 출력 문자열로 서식 지정
- 인쇄 가능한 문자열을 숫자값으로 구문 분석
- 싱글 바이트와 확장 문자 문자열 인코딩 간 상호 변환
- 싱글 바이트나 확장 문자 문자열을 멀티 바이트 문자의 문자열과 상호 변환 (C95 이후)
4. 제한
널 종단 문자열은 구현은 간단하지만, 오류 발생 가능성과 성능 문제 등 몇 가지 제한점이 있다.
- 보안 문제: 널 종단 방식은 보안 문제를 일으킬 수 있다.[25] 문자열 중간에 삽입된 널 바이트(null byte)는 문자열을 의도치 않게 잘라버릴 수 있으며, 널 문자를 위한 공간을 할당하지 않아 인접 메모리를 덮어쓰는 버그도 발생할 수 있다.
- 성능 문제: 문자열 길이를 구하는 연산은 O(n)의 시간을 소요하며, 0을 저장할 수 없다는 특성 때문에 텍스트 데이터와 이진 데이터를 구분하여 처리해야 하므로 코드 중복과 오류 발생 가능성이 높아진다.
이러한 문제점들로 인해 널 종단 문자열을 사용할 때는 주의가 필요하며, 더 안전하고 효율적인 대안을 고려하는 것이 좋다. `strlcpy`와 같은 함수를 사용하여 일부 문제를 완화할 수 있지만, 완벽한 해결책은 아니다.
4. 1. 보안 문제
널 종단은 역사적으로 보안 문제를 일으켜왔다.[25] 문자열 중간에 삽입된 널 바이트는 예측하지 못하도록 문자열을 잘라버린다. 일반적인 버그는 널 문자를 위한 추가적인 공간을 할당하지 못하는 것으로, 이로 인해 인접한 메모리를 초과하여 기록되는 것이다. 또 다른 버그는 널 문자를 아예 기록하지 않는 것인데, 테스트 중에는 발견하지 못할 때가 있다. 이는 널 문자가 우연히 과거의 동일한 메모리 블록을 사용하고 있기 때문이다.[6][7]문자열 길이를 찾는 데 시간이 많이 소요되기 때문에, 많은 프로그램은 고정 크기 버퍼에 문자열을 복사하기 전에 문자열 길이를 확인하지 않았다. 따라서 문자열이 너무 길 경우 버퍼 오버플로우를 일으켰다.[16]
0을 저장할 수 없다는 점 때문에 텍스트 데이터와 바이너리 데이터를 구분하여 별도의 함수로 처리해야 한다 (후자의 경우 데이터의 길이도 함께 제공해야 한다). 이는 코드 중복을 유발하고, 잘못된 함수가 사용될 경우 오류가 발생할 수 있다.
4. 2. 성능 문제
문자열 길이를 구하는 작업은 O(''n'')의 시간 복잡도를 가지므로, 빈번하게 호출될 경우 성능 저하를 유발할 수 있다.[7] 0을 저장할 수 없어 텍스트 데이터와 바이너리 데이터를 구분하여 별도의 함수로 처리해야 하며(후자의 경우 데이터의 길이도 함께 제공해야 한다), 이는 코드 중복 및 오류 발생 가능성을 높인다.[16]길이를 찾는 속도 문제는 `strlcpy`와 같이 O(''n'')의 다른 연산과 결합하여 완화할 수 있지만, 항상 직관적인 API를 제공하는 것은 아니다.
5. 문자 인코딩
널 종단 문자열은 문자 배열 내에서 값이 0인 요소를 감시병으로 사용하기 때문에, 값이 0이 되는 문자를 포함하지 않는 인코딩 방식이 필요하다. 1바이트 단위로 인코딩하는 경우, 값이 0이 되는 바이트를 포함해서는 안 된다.
ASCII에서는 0x00을, 유니코드에서는 U+0000을 널 문자(NUL)로 정의하고 있기 때문에[17], 널 종단 문자열에 널 문자를 그대로 포함할 수 없다[18][19][20]。 따라서 널 문자를 포함하지 않거나, 널 문자를 다른 문자나 문자열로 대체한 ASCII나 유니코드의 하위 집합을 사용한다.
자바 문자열 클래스는 널 종단이 아니며 길이 정보를 별도로 보관하므로, 내부 문자열에 널 문자를 직접 포함할 수 있다. 그러나 인코딩을 지정하여 바이트 배열에서 자바 문자열을 생성하거나[21], 자바 네이티브 인터페이스에서 자바 문자열을 C 언어의 `char`형 널 종단 문자열로 변환할 때[22]는 수정 UTF-8이 인코딩으로 사용된다.
5. 1. UTF-8 과의 관계
널 종단 문자열은 인코딩에서 0 바이트(0x00)를 사용하지 않아야 하므로, 모든 ASCII 또는 UTF-8 문자열을 저장할 수는 없다.[8][9][10] 그러나 널 종단 문자열에 NUL을 제외한 문자, 즉 ASCII 또는 UTF-8의 하위 집합을 저장하는 것이 일반적이다.일부 시스템에서는 널 문자(NUL)를 두 개의 0이 아닌 바이트(0xC0, 0x80)로 인코딩하는 "수정된 UTF-8"을 사용하기도 한다. 이를 통해 모든 문자열을 저장할 수 있지만, 이는 과잉 인코딩으로 간주되어 UTF-8 표준에서는 허용되지 않으며 보안 위험으로 간주된다.[17][18][19][20] 예를 들어 C0 80 NUL은 보안 확인에서는 문자열 종단으로, 실제 사용 시에는 문자로 간주될 수 있다.
UTF-16은 2바이트 정수를 사용하고, 바이트 중 하나가 0일 수 있으므로 널 종단 바이트 문자열에 저장할 수 없다. 그러나 일부 언어에서는 16비트 NUL(0x0000)로 종료되는 16비트 UTF-16 문자열을 구현하기도 한다.
5. 2. UTF-16 과의 관계
UTF-16은 2바이트 정수를 사용하며, 바이트 중 하나가 0일 수 있으므로 (ASCII 텍스트를 나타낼 때는 ''다른 모든'' 바이트가 0이다) 널 종단 바이트 문자열에 저장할 수 없다.[8] 그러나 일부 언어는 16비트 널(0x0000)로 종료되는 16비트 UTF-16 문자로 구성된 문자열을 구현한다. 이 경우, 싱글 바이트(8비트)의 널 문자를 상정하고 있는 기존의 문자열 조작 함수는 사용할 수 없으며, 16비트의 널 종단 문자열 전용의 함수가 필요하게 된다. 마이크로소프트 윈도우에서는 와이드 문자가 2바이트 문자형으로 정의되어, 와이드 문자의 배열을 UTF-16의 널 종단 문자열로 취급한다.[9][10]6. 개선
C 문자열 처리의 오류를 줄이기 위해 다양한 시도가 이루어졌다. 주요 개선 방법은 다음과 같다.
- 안전한 함수 추가:
strdup
및strlcpy
와 같이 더 안전한 함수를 추가하고,gets
와 같이 안전하지 않은 함수의 사용을 폐지하는 방법이 있다. - 객체 지향 래퍼: C 문자열을 둘러싼 객체 지향 래퍼를 추가하여 안전한 호출만 수행하도록 하는 방법이 있다. 그러나 이 방법으로도 안전하지 않은 함수를 호출하는 것이 가능하다.
- 현대적인 라이브러리: 대부분의 최신 라이브러리는 C 문자열을 32비트 이상의 길이 값을 포함하는 구조로 대체하고, 포인터, 참조 횟수, 널 문자(NUL) 등을 추가하여 C 문자열로의 변환 속도를 높인다. 현대의 메모리 환경에서는 각 문자열에 몇 바이트를 추가하는 것이 큰 문제가 되지 않으며, 작은 문자열이 많은 경우에는 해시 테이블 등의 다른 저장 방법이 메모리를 더 절약할 수 있다. 이러한 라이브러리의 예시로는 C++ 표준 템플릿 라이브러리의 `std::string`, Qt의 `QString`, MFC의 `CString`, Core Foundation의 `CFString`, Foundation의 `NSString` 등이 있다. rope와 같은 더 복잡한 자료 구조를 사용하여 문자열을 저장하기도 한다.[23]
6. 1. 안전한 함수 추가
C 문자열 처리는 오류 발생 가능성을 줄이기 위해 많은 시도가 이루어졌다. 한 가지 방법은 `strdup`이나 `strlcpy`처럼 더 안전한 함수를 추가하고, `gets` 같이 안전하지 않은 함수의 사용을 중단하는 것이다. 다른 방법으로는 C 문자열을 객체 지향 래퍼로 감싸서 안전한 호출만 가능하게 하는 것이 있다. 하지만 안전하지 않은 함수를 호출하는 것이 아예 불가능한 것은 아니다.6. 2. 객체 지향 래퍼
C 문자열을 둘러싼 객체 지향 래퍼를 추가하여 안전한 호출만 수행하도록 할 수 있다. 그러나 안전하지 않은 함수를 호출하는 것도 가능하다.[23]6. 3. 현대적인 라이브러리
대부분의 최신 라이브러리는 C 문자열을 32비트 이상 길이 값을 포함하는 구조로 대체하고, 포인터, 참조 횟수, 널 문자(NUL) 등을 추가하여 C 문자열로의 변환 속도를 높인다. 현대의 메모리 환경에서는 각 문자열에 몇 바이트를 추가하는 것이 큰 문제가 되지 않으며, 작은 문자열이 많은 경우에는 해시 테이블 등의 다른 저장 방법이 메모리를 더 절약할 수 있다. 이러한 라이브러리의 예시로는 C++ 표준 템플릿 라이브러리의 `std::string`, Qt의 `QString`, MFC의 `CString`, Core Foundation의 `CFString`, Foundation의 `NSString` 등이 있다. rope와 같은 더 복잡한 자료 구조를 사용하여 문자열을 저장하기도 한다.[23]참조
[1]
웹사이트
Chapter 15 - MIPS Assembly Language
https://people.scs.c[...]
2023-10-09
[2]
학회자료
The development of the C language
https://www.bell-lab[...]
1993-04
[3]
서적
History of Programming Languages
ACM Press
[4]
문서
IBM z/Architecture Principles of Operation
http://publibfp.dhe.[...]
[5]
간행물
The Most Expensive One-byte Mistake
http://queue.acm.org[...]
2011-07-25
[6]
학술지
Perl CGI problems
http://insecure.org/[...]
artofhacking.com
2016-01-03
[7]
웹사이트
Null byte injection on PHP?
https://security.sta[...]
[8]
웹사이트
UTF-8, a transformation format of ISO 10646
http://tools.ietf.or[...]
2013-09-19
[9]
웹사이트
Unicode/UTF-8-character table
http://www.utf8-char[...]
2013-09-13
[10]
웹사이트
UTF-8 and Unicode FAQ
http://www.cl.cam.ac[...]
2013-09-13
[11]
문서
文字はASCIIだけに限らないことに注意。
[12]
웹사이트
Warning C6053 | Microsoft Learn
https://learn.micros[...]
[13]
학회자료
The development of the C language
1993
[14]
간행물
The Most Expensive One-byte Mistake
http://queue.acm.org[...]
2011-08-02
[15]
웹사이트
The Development of the C Language
http://cm.bell-labs.[...]
2011-11-09
[16]
학술지
Perl CGI problems
http://artofhacking.[...]
artofhacking.com
2012-01-06
[17]
웹사이트
U+0000
[18]
웹사이트
UTF-8, a transformation format of ISO 10646
https://datatracker.[...]
2013-09-19
[19]
웹사이트
Unicode/UTF-8-character table
http://www.utf8-char[...]
2013-09-13
[20]
웹사이트
UTF-8 and Unicode FAQ
http://www.cl.cam.ac[...]
2013-09-13
[21]
문서
[22]
웹사이트
Java Native Interface Specification: 4 - JNI Functions
https://docs.oracle.[...]
[23]
웹사이트
std::basic_string
[24]
웹인용
The Development of the C Language
http://cm.bell-labs.[...]
2011-11-09
[25]
저널 인용
Perl CGI problems
http://insecure.org/[...]
artofhacking.com
2016-01-03
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com