[C] 읽기 전용 메모리 공간
안녕하세요. 밥한그릇입니다 ^^
오늘 친구와 연락을 하던 중 C언어의 '읽기 전용 메모리'에 관한 내용을 새롭게 알게되어, 오랜만에 포스팅을 쓰게 되었습니다.
그럼 시작합니다~
C언어는 프로그래밍 언어의 기본으로도 여겨지며, 하드웨어와 관련된 많은 api를 제공하고 직접 메모리를 할당-해제합니다. 따라서 사람의 언어보다는 기계의 방식에 더 가까운 low-level 언어로 분류되고 있습니다.
저 또한 C언어를 주력 언어로 사용해왔으나, 보통 개발 시 사용하게 되는 C언어의 기능이 제한적인 만큼 '읽기전용 메모리 공간'에 대한 내용은 오늘 처음 접하게 되었습니다. 따라서 포스팅을 통해 그 설명과 기록을 해두고자 합니다.
📟 메모리 공간
4개의 메모리 segment
메모리 공간은 OS에 의해 할당되어, 물리적 주소가 아닌 논리적 주소의 형태로 다음과 같이 연속적으로 존재합니다.
여기에는 stack 영역, heap 영역, 데이터 영역, code(text) 영역이 있습니다.
잘 알려져있다시피 스택 영역은 지역 변수들과 함수의 호출 정보 등을 저장하며, 힙 영역은 우리가 동적할당한 데이터들을 저장하게 됩니다.
데이터 영역은 주로 전역변수와 정적 변수 등을 저장하며, 프로그램의 시작과 함께 메모리가 할당되어 프로그램이 끝나면 소멸합니다. 코드 영역은 컴파일 시간에 결정된 코드와 상수가 기계어로 저장되어 있습니다.
Stack과 Heap은 메모리 주소공간의 위 아래에서 서로를 마주보며 영역을 확장하는 구조입니다.
각 segment에서의 읽기/쓰기 권한
이때 각 영역에 대한 읽기/쓰기 권한이 서로 다릅니다.
Read-only(읽기 전용) 영역에서는 메모리에 대한 읽기만 가능하고, 쓰기는 불가능합니다. 그렇지만 Read-Write 영역에서는 메모리 공간에서 데이터를 읽고 쓰는 것 모두가 가능합니다.
코드 영역은 컴파일 이후 그 내용이 변경되면 안되므로 Read-only 영역입니다. 반면에 Stack 영역과 Heap 영역은 내용을 읽는 것도 가능하고, 내용을 바꾸고 새로 쓸 수도 있는 Read-Write 영역입니다.
그러면 data 영역은 어떤 영역일까요. Read-Only일까요 아니면 Read-Write일까요?
네. 정답은 둘 다입니다 (!!!)
읽기 전용 메모리 공간과 읽기-쓰기가 모두 가능한 메모리 공간이 모두 있습니다.
이 점을 기억해두시고 다음 설명으로 넘어갑시다.
🔍 읽기 전용 메모리 공간
앞서 설명하면서, 메모리의 data segment 영역에 읽기 전용 메모리와 읽기-쓰기 모두 가능한 메모리가 따로 있다고 했습니다.
이때 이 읽기 전용 메모리 공간을 C에서 쓸 수 있는데요.
어떻게 하면 읽기 전용 메모리 공간을 사용하는 지 예시를 통해 보도록 하겠습니다.
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
int main()
{
char *s1 = "Hello"; // 문자열 포인터
char *s2 = ""; // 문자열 포인터
strcpy(s2, s1); // 실행 에러
printf("%s\n", s2);
return 0;
}
다음의 코드를 실행하면 에러가 납니다. 왜 일까요?
읽기 전용 메모리끼리 복사(쓰기)를 수행하려고 하였기 떄문입니다.
char *p = "문자열" 과 같은 형식으로, 포인터의 값을 바로 할당해주게 되면, 이 데이터는 읽기 전용 data 섹션에 저장됩니다.
따라서 이러한 메모리 관련 오류를 일으키지 않게끔, 읽기전용 메모리에 대해서도 확실히 알아두는 것이 좋겠습니다.
포인터와 메모리 관련 개념이 확실히 잡히지 않은 경우, 더욱 헷갈릴 수 있는 부분이라고 생각합니다.
char *s1 = "Hello"; char *s2 = "";과 같은 문자열 포인터에 할당된 문자열 리터럴은 왜 읽기 전용일까요?
C 언어 컴파일러는 문자열 포인터에 할당한 문자열 리터럴을 실행 파일의 읽기 전용 데이터 섹션(데이터 세그먼트)에 배치하기 때문입니다. 따라서 실행 파일이 실행된 뒤에는 읽기 전용 메모리가 되며 쓰기를 할 수 없습니다. 다음은 각 운영체제별 읽기 전용 데이터 섹션 이름입니다.
- Windows PE: .rdata
- 리눅스 ELF: .rodata
- OS X Mach-O: __TEXT, __cstring
참고 자료
COS Pro 2급 C 언어: 38.1 문자열 복사하기
38 문자열을 복사하고 붙이기 이번에는 문자열을 다른 곳으로 복사하는 방법과 두 문자열을 붙이는 방법을 알아보겠습니다. 38.1 문자열 복사하기 문자열은 다른 배열이나 포인터(메모리)로 복사
dojang.io
이 포스팅을 작성할 때 C언어 코딩도장의 내용과 코드 예시를 참고하였습니다.
'IT > 학과 공부' 카테고리의 다른 글
[전공] C에서의 변수의 scope와 lifetime (0) | 2022.06.11 |
---|---|
[컴파일러] LR 파서 문제 풀이 (0) | 2022.06.11 |
[컴파일러] LL(1) 파서 문제 풀이 (0) | 2022.06.11 |
[컴파일러] LL 파서와 LR 파서 (0) | 2022.06.10 |
C에서 시그널을 보내고 처리하는 방법 (kill, signal, sigaction) (0) | 2022.01.06 |