C语言跨进程访问内存为何触发Segmentation Fault?
为什么直接使用另一个进程的指针地址会触发Segmentation Fault?
这个问题的核心在于现代操作系统的进程地址空间隔离机制,咱们一步步拆解原因:
1. 每个进程的虚拟地址空间是完全独立的
现代操作系统(比如Linux、Windows)都采用了虚拟内存机制,每个运行的进程都会获得一套属于自己的虚拟地址空间。这意味着:
- 第一个程序里输出的
0x7ffebbd57fc8只是它自身进程的虚拟地址,这个地址在第二个进程的地址空间里,要么没有映射到任何物理内存,要么你没有访问权限。 - 当第二个进程尝试访问这个地址时,操作系统会检测到非法内存访问,直接触发Segmentation Fault终止程序。
2. 你混淆了「指针变量的地址」和「指针指向的内存地址」
仔细看第一个程序的代码:
printf(" foo addr : %p\n\n" ,&foo);
这里你打印的是指针变量foo本身在栈上的地址,而不是foo指向的、通过malloc分配的堆内存地址。如果你的目的是想访问malloc出来的那个存着s的内存,你应该打印foo而不是&foo:
printf(" foo points to : %p\n\n" , foo); // 这才是堆内存的地址
但就算你拿到了堆内存的地址,第二个进程依然无法访问——因为那块堆内存属于第一个进程的地址空间,第二个进程没有权限触碰。
3. 跨进程访问内存的正确姿势
如果需要在两个进程间共享数据,不能直接硬编码地址,必须使用操作系统提供的跨进程通信(IPC)机制,比如:
- 共享内存:Linux下用
shmget/shmat系列函数,Windows下用CreateFileMapping - 管道:匿名管道或命名管道
- 消息队列
- 套接字(即使是本地进程也可以用Unix域套接字)
这些机制由操作系统协调,能保证内存访问的合法性和安全性。
举个修正后的第一个程序例子(只是纠正地址打印问题,依然不能跨进程访问):
#include <stdio.h> #include <stdlib.h> int main(){ char* foo=(char*) malloc(1); *foo='s'; printf(" foo points to : %p\n\n" , foo); // 打印指向的堆内存地址 int pause; scanf("%d",&pause); free(foo); // 记得释放malloc的内存 return 0; }
内容的提问来源于stack exchange,提问作者Seçkin Güleviz
相关产品推荐
相关产品推荐

