C语言父子进程共享内存输出无间隔问题求助(Collatz猜想场景)
问题分析与修复
你的核心问题是子进程中计算共享内存指针偏移的逻辑完全错误:
你用char *a = (char *) &n; ptr += strlen(a);来计算偏移,这里&n是int变量的内存地址,strlen(a)会把int的二进制数据当作字符串读取,直到遇到字节0,这和数字转成字符串后的长度毫无关系,导致ptr的偏移量远小于实际写入的字符数,后续的sprintf会直接覆盖之前写入的空格,最终所有数字连在一起。
修复方案
正确的偏移计算方式
每次调用sprintf后,直接用它的返回值(返回写入的字符总数,不含终止符)来偏移ptr;或者用strlen(ptr)获取当前写入的字符串长度再偏移,两种方式都可以。
修正后的代码
#include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <wait.h> #include <fcntl.h> #include <sys/shm.h> #include <sys/stat.h> #include <string.h> #include <sys/mman.h> int main(int argc, char** argv){ const int SIZE = 4096; // Shared memory size const char* name = "COLLATZ"; // Shared Memory Name int n = atoi(argv[1]); pid_t pid = fork(); // process divergence int shm_fd; // shared memory file descriptor void *ptr; // shared memory pointer shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666); // create shared memory object ftruncate(shm_fd, SIZE); // configure size of the shared memory ptr = mmap(0, SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, shm_fd, 0); // 父进程需要读权限,添加PROT_READ close(shm_fd); // 映射完成后可关闭文件描述符,不影响共享内存使用 if(pid == 0){ // 子进程:生成Collatz序列写入共享内存 char *current_ptr = ptr; // 用临时指针记录当前写入位置,逻辑更清晰 while(n > 1){ // 用sprintf返回值获取写入字符数,直接偏移指针 int written = sprintf(current_ptr, "%d ", n); current_ptr += written; // Collatz序列逻辑 if(n % 2 == 0){ n = n / 2; } else { n = 3 * n + 1; } } // 写入最后一个数字,末尾不加空格 sprintf(current_ptr, "%d", n); } else if(pid > 0){ wait(NULL); printf("%s\n", (char *)ptr); // 读取共享内存起始位置的内容 } shm_unlink(name); // 删除共享内存对象 return 0; }
额外优化点
- 父进程映射共享内存时添加
PROT_READ权限,权限配置更合理。 - 映射完成后关闭
shm_fd,避免资源泄漏。 - 最后一个数字后不再写入空格,避免输出末尾多余空格。
- 用临时指针
current_ptr记录写入位置,避免修改原ptr,代码逻辑更清晰。
测试结果
运行程序输入./your_program 8,会正确输出:8 4 2 1
内容的提问来源于stack exchange,提问作者Cmcbride
相关产品推荐
相关产品推荐

