2009-11-10 2 views
19

은 내가C에서 읽기 전용 메모리는 어떻게 구현됩니까?

char *s = "hello world". 

을 C에서, 경우에 "Hello World"가 실제로 읽기 전용 메모리에 저장되어 있다고 들었습니다.

읽기 전용 메모리에 대해서는 분명치 않습니다. 설명은 무엇입니까? 그것은 컴파일러에게 해당 섹션에 쓰지 않도록 알려주는 플래그와 같은 것입니까?

+1

당신은 참조를 가지고 있습니까? 내 생각에 당신이 의미 할 수도 있습니다 : const char * s = "hello world". –

+3

모든 프로세서 아키텍처가 보호 된 메모리를 지원한다는 것은 분명하지 않습니다. – jldupont

+1

@James Black : OP는 분명히 포인터가 선언 된 방법에 관계없이 읽기 전용 메모리에 실제로 저장 될 수있는 문자열 리터럴 인 "hello world"에 대해 이야기하고 있습니다. – AnT

답변

27

/이론적 프로그램이 자체 메모리를 수정할 수 있어야합니다 -

내가 읽기 전용으로 왜 확실하지 않다, 그런 말로 미루어 링커 및 운영 시스템이 함께 작동합니다.

다음과 같은 일이 같은 코드를 컴파일

는 :

  • 컴파일러는 읽기 전용 데이터 섹션에 문자열을 넣어 것입니다.

  • 링커는 읽기 전용 섹션의 모든 데이터를 수집하여 단일 세그먼트에 넣습니다. 이 세그먼트는 실행 파일에 있으며 "읽기 전용"속성으로 플래그됩니다.

  • 이제 운영 체제 실행 가능 로더가 제공됩니다. 그것은 실행 파일을로드합니다 (또는 더 정확하게는 메모리에 매핑합니다). 이 작업이 완료되면 로더는 섹션을 탐색하고 각 세그먼트에 대한 액세스 권한을 설정합니다. 읽기 전용 데이터 세그먼트의 경우 코드 실행 및 쓰기 액세스가 비활성화 될 가능성이 큽니다. 코드 (예 : 함수)는 실행 권한을 가지지 만 쓰기 권한은 없습니다. 정적 변수와 같은 일반 데이터는 읽기 및 쓰기 액세스 등을 얻습니다. ...

이제는 최신 운영 체제에서 사용합니다.

마찬가지로 C 언어의 기능은 아닙니다. 예를 들어, DOS에서 같은 문제를 컴파일하면 프로그램이 실행되지만 DOS 로더가 읽기 전용 섹션을 알지 못하기 때문에 쓰기 보호는 불가능합니다.

+0

상수 변수도 "hello world"와 같은 섹션을 넣습니까? (예 : const int a = 6) – root

+0

"다릅니다." const int에 대해 확실히 말할 수있는 유일한 것은 컴파일러가 수정하려고하면 진단 메시지를 생성한다는 것입니다. 읽기 전용 섹션에 저장 될 수도 있고 전혀 저장되지 않을 수도 있으며이를 사용하는 명령어에 상수로 직접 인코딩 될 수도 있습니다. –

+0

@tsubasa - 아마 그렇지는 않습니다. 물론'a'가 로컬 일 경우는 아닙니다. 그러나 대답이 무엇이든 OS와 로더에 따라 달라집니다. –

3

진정한 읽기 전용 메모리는 OS의 메모리 하위 시스템에서 구현됩니다. OS는 특정 페이지를 읽기 전용으로 표시 할 수 있습니다.

바이너리에서 컴파일러는 실행 파일의 어느 부분을 읽기 전용 메모리와 읽기 - 쓰기 메모리 페이지에 배치해야하는지 OS에 알릴 수 있습니다.

+1

hmmm ... 진정한 메모리 보호는 프로세서 수준에서 구현됩니다. – jldupont

+0

@jldupont : 메모리 보호는 실제로 하드웨어 수준에서 (적어도 x86에서) 시행되지만 초기 설정은 OS, 즉읽기 전용 페이지를 표시하는 OS가있는 경우 하드웨어는 OS가 설정 한 읽기 전용 표시를 적용합니다. – AnT

+0

@ 안드레이 T : 물론 ... 내 포인트는 @ R 사무엘에 관한 것이었다. 하드웨어 ** 지원이 없으면 소프트웨어 수준에서 많은 도움을받을 수 있습니다. – jldupont

6

실행 파일에는 전역 변수를 포함하는 .data 섹션과 실제 시스템 코드가 들어있는 .text 섹션이 있습니다.

문자열이 .data 섹션에 배치됩니다. C는 "Hello world"라는 문자열을 "Hello world"라고하고 실행 파일 자체에 넣고 프로그램의 "Hello world"인스턴스를 해당 문자열이로드되는 주소로 바꿉니다. ..

C language의 기능을하지만, 컴파일러의 기능이 아니다
+2

일부 프로세서 및 운영 체제가 자체 수정 코드를 지원하는 것은 아닙니다. 사실 최신 운영 체제에는 보안 기능으로 자체 수정 코드에 대한 보호 기능이 포함되어 있습니다. – Crashworks

+0

문자열 리터럴은 수정할 필요가 없기 때문에 텍스트 섹션에 저장 될 수 있으며 종종 저장됩니다. – caf

2

Linux에서이 작업을 수행하는 방법의 예는 Mark Mitchell, Jeffrey Olham 및 Alex Samuel이 page 179 of Advanced Linux Programming에 있습니다.그것이 말하는 경우

+0

굉장한 책입니다 .. 2 년 뒤에도 :) ... – bsoundra

0

당신은

s[4] = '0'; 

같은 것을 시도하고 볼 수 있었다 "안녕하세요 w0rld"은 다음을 즉시 분할의 오류 또는 데이터 실행 방지 (DEP) 예외가 발생하는 경우가

puts(s); 

전화 아마 읽기 전용입니다. (시스템으로 도망 갈 수 있다면 좋은 아이디어는 아닙니다.)

1

다른 사람들이 언급했듯이 상수 문자열의 내용이 읽기 전용 메모리에 저장되어 있는지 여부는 운영 체제에 의해 결정됩니다 시스템, 컴파일러 및 칩 아키텍처를 지원합니다.

보다 정확하게, C 표준은 인용 된 문자열이 "const char []"유형 (또는 그 효과가있는 단어들, 나는 당면 표준을 가지고 있지 않다)을 가지고 있다고 간주한다.

이러한 문자열의 내용을 수정하려고 시도하는 코드는 정의되지 않은 동작을 호출합니다. 즉, 문자 그대로 아무것도 그 시점에서 일어날 수 있고 컴파일러의 제공자는 일어날 수있는 일을 문서화 할 필요조차 없다는 것을 의미합니다.

실제로 이것은 이동 가능한 C 또는 C++ 프로그램이 상수 문자열을 수정하지 않아야 함을 의미합니다.

일반적으로 컴파일러에서는 "const"변수의 내용을 수정할 수 없으므로 대부분의 경우 "const"를 "읽기 전용"으로 간주 할 수 있습니다. 불행히도 char *와 const char *에 대한 특별한 예외가있다. 이는 다음과 같은 코드를 의미합니다.

char *x = "Hello, World"; 
*x = 'h'; 

은 정의되지 않은 동작을 호출하더라도 오류 또는 경고없이 컴파일됩니다.

0

쓸 때 char s[10]="sneha"; 당신은 당신의 목적 파일에서 10 바이트의 저장 공간 (메모리가 아닌 메모리는 프로그램을 실행할 때만 나타납니다)을 할당하고 있습니다. 이것은 메모리의 정적 할당입니다 (컴파일 타임에).

그러나 char *s="sneha";을 쓸 때 "sneha"을 저장할 저장 공간을 할당하지 않습니다. READ ONLY 섹션에 저장됩니다. 그러나 포인터 s은 선언 된 위치에 따라 다른 섹션에 저장됩니다. 그러나 READ ONLY DATA "sneha"을 가리키고 있습니다. 그래서 당신이 그것을 쓰려고하면 당신은 세분화 오류를 얻을 것이다. 예를 들어

:

char *s[10]="sneha"; 
s[1]="N"; 
printf("%s",s); // you expecting output sNeha, 
       // but you get a seg fault since it is ONLY DATA 
관련 문제