Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我可以访问内存中的任何内容吗?_C_Pointers_Memory Management - Fatal编程技术网

C 我可以访问内存中的任何内容吗?

C 我可以访问内存中的任何内容吗?,c,pointers,memory-management,C,Pointers,Memory Management,免责声明:我是C/C++新手 如果我在C中输入一个变量,然后尝试回显该值……我是否可以不受限制地查看内存中的任何内容,或者是否存在限制 例如: char * p = (char *)0x28ff44; printf("Memory value: %c", *p); 我猜如果地址上的内容不符合char类型的大小,那么它会崩溃得很厉害,但这只是一个例子。我真正好奇的是,这样的事情是否可能发生,或者操作系统是否施加了限制,只允许您访问给定内存空间中的内存?这取决于您的程序运行的计算机体系结构和操作系

免责声明:我是C/C++新手

如果我在C中输入一个变量,然后尝试回显该值……我是否可以不受限制地查看内存中的任何内容,或者是否存在限制

例如:

char * p = (char *)0x28ff44;
printf("Memory value: %c", *p);

我猜如果地址上的内容不符合char类型的大小,那么它会崩溃得很厉害,但这只是一个例子。我真正好奇的是,这样的事情是否可能发生,或者操作系统是否施加了限制,只允许您访问给定内存空间中的内存?

这取决于您的程序运行的计算机体系结构和操作系统。现代操作系统有内存和内存的概念。对于虚拟内存,内存地址不是指物理内存,而是指分配给当前应用程序的虚拟内存空间。在这些情况下,试图读取或写入指定内存空间之外的内存将导致程序故障(通常是分段故障或保护故障)。

带有内存管理单元(MMU)的系统很可能不允许您访问任意内存。任何现代操作系统都使用内存保护。但在嵌入式领域,有许多操作系统不采用内存保护,而且确实可以访问任何可寻址内存。

哦,天哪,好吧

从技术上讲,是的,你可以。在不使用MMU或任何形式的保护的嵌入式设备中(或者,您知道,在实模式下使用x86),您可以完全按照发布的方式进行操作。您也可以在任何操作系统上以用户模式执行此操作,但实际命中有效内存的可能性非常小

事实上,不,你不能这么做。给定虚拟内存和内存保护,您尝试访问的区域很可能没有映射,因此将失败。此外,如果您点击受保护的内存(例如,属于操作系统的任何内容),您的访问将失败。这两种情况都是导致分段错误的原因

您的语句是有效的(对于valid的不同定义),程序将尝试访问您请求的内存。只是它实际上可能没有映射到任何东西

还值得注意的是,内存映射I/O就是这样工作的。假设我有一个硬件控制寄存器,当写入时,它会在连接的UART/串行线上写入一个字节(为了简单起见,它就像魔术一样工作,不需要设置任何其他寄存器)。在C语言中,对于我过于简化的设备,这将被写成如下内容:

#define UART1_OUT 0xFC56   

volatile char* uart = UART1_OUT;   // Definition of pointer to variable.
                                   // volatile is required here. Look it up, but
                                   // it basically stops your compiler optimising
                                   // anything to do with this variable

*uart = 'A';                       // Write an A character to the serial line
当然,现实世界的设备要复杂一点;)

如果我手动为C中的变量分配一个内存地址 然后尝试回显该值…我是否可以不受限制地访问 查看内存中的任何内容或是否存在限制

C语言很乐意让您尝试,但大多数操作系统不允许您访问进程内存空间之外的内存。如果您正在为一个嵌入式系统编写代码,而您的代码和硬件之间的距离不太远,那么您可能可以在任何您喜欢的位置进行读写。但是,如果您正在为具有受保护内存的系统编写代码,则不需要太多

我猜如果那个地址是什么的话,它会崩溃得很厉害 不适合字符类型的大小


不。。。编译器不关心在任何给定地址存储什么类型的数据。当你说
(char*)0x28ff44
时,你是在告诉它
0x28ff44
是一个
char*
,这对编译器来说已经足够好了。您的代码可能仍然会由于其他原因而崩溃,例如
0x28ff44
不是有效地址。

所以有些操作系统允许这种公然入侵其他应用程序和/或操作系统本身的内存空间?啊,好的。因此,使用虚拟内存,我不会“意外”使其他程序或操作系统崩溃?@cillosis:不会,因为您进程的内存空间不与任何其他进程共享。您可以在另一个有关堆栈溢出的问题中找到一些有趣的信息:哇,感谢您提供了所有精彩的答案。我记得在高中的时候(我想大概10多年前)我试着学习C语言,我似乎还记得在我涉猎的时候,通常只有一个记忆空间,而且里面可能会出现问题。很高兴看到像我这样的低级noob现在有了更多的保护。请注意,
%s
对于单个字符来说格式字符串是错误的,您需要
%c
;)C标准不允许这样做(这是“未定义的行为”),但特定平台可能会以合理的方式接受这一点。例如,当您编写一个由BIOS加载的操作系统时,您必须访问内存中的某些硬编码部分。@slugonamission感谢您指出这一点,我更改了它。我想您必须键入cast地址值,否则编译器将给出错误。不,这在GCC中是默认警告。我不确定VisualC和Clang。