C语言中的只读存储器是如何实现的?

发布于 2024-08-10 13:37:20 字数 162 浏览 7 评论 0原文

我听说在C中,如果我这样做,

char *s = "hello world". 

“hello world”实际上存储在只读存储器中。

我对只读内存不太清楚。解释是什么?这是否就像编译器的一个标志,告诉编译器不要写入该部分?

I heard that in C, if I do

char *s = "hello world". 

the "hello world" is actually stored in read-only memory.

I am not so clear about read-only memory. What is the explanation? Is that like a flag to the compiler that tells the compiler to do not write into that section?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

城歌 2024-08-17 13:37:20

这不是 C 语言 的功能,而是编译器/链接器的功能,并且操作系统一起工作。

当您编译此类代码时,会发生以下情况:

  • 编译器会将字符串放入只读数据部分。

  • 链接器收集此类只读部分中的所有数据并将它们放入单个段中。该段驻留在可执行文件中,并带有“只读”属性标记。

  • 现在是操作系统可执行加载程序。它加载可执行文件(或更准确地说,将其映射到内存中)。完成此操作后,加载程序将遍历各个部分并为每个部分设置访问权限。对于只读数据段,它很可能会禁用代码执行和写入访问。代码(例如,您的函数)获得执行权限,但没有写入权限。像静态变量这样的普通数据可以获得读写访问权限等等...

这就是现代操作系统的做法。

如前所述,这不是 C 语言的特性。例如,如果您为 DOS 编译相同的问题,程序将运行,但不可能有写保护,因为 DOS 加载程序不知道只读部分。

That's not a feature of the C language but a feature of the compiler/linker and the operating system working together.

When you compile such code the following happens:

  • The compiler will put the string into a read-only data-section.

  • The linker collects all the data in such read-only sections and puts them into a single segment. This segment resides in the executable file and is flagged with a "read only"-attribute.

  • Now comes the operating system executable loader. It loads the executable (or maps it into memory to be more exact). Once this is done, the loader walks the sections and sets access-permissions for each segment. For a read-only data segment it will most likely disable code-execute and write access. Code (for example, your functions) gets execute rights but no write access. Ordinary data like static variables gets read and write access and so on...

That's how modern operating systems do it.

As said, it's not a feature of the C language. If you compile the same problem for DOS, for example, the program will run but no write protection would be possible, because the DOS-loader does not know about read-only sections.

旧夏天 2024-08-17 13:37:20

可执行文件包含两部分:包含全局变量的 .data 部分和包含实际机器代码的 .text 部分。

字符串被放置在 .data 部分中。当 C 看到“Hello world”时,它所做的是将字符串“Hello world”放入可执行文件本身,并用该字符串最终加载的地址替换程序中“Hello world”的实例。

话虽如此,我不确定为什么它是只读的 - 理论上程序应该能够修改自己的内存。

Executables contain two parts: a .data section, containing global variables, and a .text section, containing the actual machine code.

Strings are placed into the .data section. What C does when it sees "Hello world" is it puts the string "Hello world" into the executable itself, and replaces instance of "Hello world" in the program with the address where that string ends up being loaded.

Having said that, I'm not sure why it's read-only - theoretically a program should be able to modify its own memory..

夜深人未静 2024-08-17 13:37:20

真正的只读内存是由操作系统的内存子系统实现的。操作系统可以将某些页面标记为只读。

在二进制文件中,编译器可以告诉操作系统可执行文件的哪些部分应放置在只读内存页和读写内存页中。

True read-only memory is implemented by the memory subsystem of the OS. The OS can mark certain pages as read-only.

In the binary, the compiler can tell the OS which parts of the executable should be placed in read-only vs read-write memory pages.

故笙诉离歌 2024-08-17 13:37:20

当你写 char s[10]="sneha";您在目标文件中分配了 10 个字节的存储空间(不是内存,只有在执行程序时内存才会出现)。这是内存的静态分配(在编译时)。

但是,当您编写 char *s="sneha"; 时,您并没有分配任何存储空间来存储 "sneha"。它将存储在只读部分。但是指针 s 根据声明的位置存储在不同的部分中。但它指向只读数据“sneha”。因此,如果您尝试在其上写入,则会出现分段错误。

例如:

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

When you write char s[10]="sneha"; you are allocating 10 bytes of storage space(not memory, memory comes into picture only when u r executing your program) in your object file. This is static allocation of memory( at compile time).

But when you write char *s="sneha"; you are not allocating any storage space to store "sneha". It will get stored in READ ONLY section. But the pointer s is stored in different section based on where it is declared. But it is pointing to the READ ONLY DATA "sneha". So if you try to write on it you will get segmentation fault.

For example:

char *s = "sneha";
s[1] = 'N'; 
printf("%s",s);  // you expecting output sNeha, 
                 // but you get a seg fault since it is READ ONLY DATA 
天煞孤星 2024-08-17 13:37:20

如何在 Linux 中执行此操作的示例位于 Mark Mitchell、Jeffrey Olham 和 Alex Samuel 的高级 Linux 编程第 179 页。

An example of how to do this in Linux is on page 179 of Advanced Linux Programming by Mark Mitchell, Jeffrey Olham, and Alex Samuel.

坦然微笑 2024-08-17 13:37:20

您可以尝试类似的操作

s[4] = '0';

,看看当您调用时它是否显示“hello w0rld”。

puts(s);

如果它导致立即分段错误或数据执行保护异常,那么它可能是只读的。 (如果系统让你侥幸逃脱,那这并不是一个好主意。)

You could try something like

s[4] = '0';

and see if it says "hello w0rld" when you call

puts(s);

If it causes an immediate Segmentation Fault or a Data Execution Prevention exception then it is probably read only. (If the system lets you get away with it, that doesn't make it a good idea.)

白昼 2024-08-17 13:37:20

正如其他人提到的,常量字符串的内容是否存储在只读存储器中是由操作系统、编译器和芯片架构决定的。

更准确地说,C 标准指定引用的字符串被视为具有“const char[]”类型(或具有这种效果的单词,我手头没有标准)。

任何尝试修改此类字符串内容的代码都会调用未定义的行为。这意味着此时任何事情都可能发生,并且编译器的提供者甚至不需要记录可能发生的情况。

实际上,这意味着想要可移植的 C 或 C++ 程序必须避免修改常量字符串。

一般来说,编译器不允许你修改“const”变量的内容,因此在大多数情况下你可以认为“const”意味着“只读”。不幸的是,char * 和 const char * 有一个特殊的例外,这主要是由于历史原因。这意味着像这样的代码:

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

即使它调用未定义的行为,也将编译而不会出现错误或警告。

As other folks have mentioned, whether the contents of constant strings are stored in read-only memory is determined by the operating system, compiler, and chip architecture.

More precisely, the C standard specifies that the quoted strings are considered to have "const char[]" type (or words to that effect, I don't have the standard at hand).

Any code that attempts to modify the contents of such a string is invoking undefined behavior. That means that literally anything can happen at that point, and the provider of the compiler isn't even required to document what can happen.

In practice, this means that a C or C++ program that wants to be portable has to avoid modifying constant strings.

In general, the compiler will not allow you to modify the contents of of "const" variables, so you can consider "const" to mean "read only" in most cases. Unfortunately, there's a special exception for char * and const char *, largely for historical reasons. That means that code like this:

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

will compile without error or warning, even though it invokes undefined behavior.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文