You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用POSIX读写结构体到共享内存时遇权限错误与段故障

POSIX共享内存读写结构体时的权限与段错误问题

问题描述

尝试通过POSIX接口将结构体读写至共享内存,但程序因权限问题和段错误崩溃。其中Write.cpp在输入值后会陷入循环,最终提示struct failed: cannot allocate memory并触发段错误。

原始代码

Write.cpp

#include<iostream>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<sys/file.h>
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
#include<dirent.h>
#include<string.h>
#include"headerfile.h"
using namespace std;
int main()
{
        int fd;
        char *pg_addr;
        int size =10000;
        int mode = S_IRWXO|S_IRWXG|S_IRWXU;
        int i=0;
        while(1)
        {
                cout<<"\nenter 1 to read again and 2 to exit : ";
                cin>>i;
                if(i==2)
                        break;

                fd=shm_open("memory_exp1",O_RDONLY, 0666);
                if (fd == -1)
                perror("shm_open");
                struct shmbuf *shmp = (shmbuf*)mmap(NULL,sizeof(*shmp),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
                if(shmp==MAP_FAILED)
                        perror("MMap error");        
                cout <<"\n Read data is" << shmp->buf << "\n" << shmp->cnt;        
        }
        close(fd);
        return 0;
}

Read.cpp

#include<iostream>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<sys/file.h>
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
#include<dirent.h>
#include<string.h>
#include"headerfile.h"
using namespace std;
int main()
{
        cout<<"point1";
        int fd;
        char *pg_addr;
        int size =10000;
        int i=0;
        char strTemp[100]="";
         int mode = S_IRWXO|S_IRWXG|S_IRWXU;


    fd=shm_open("memory_exp1",O_CREAT,mode);
        while(1)
        {
                cout<<"\nEnter 2 to exit\nto continue press any other value :";
                cin >> i;
                if(i==2)
                        break;
                fd=shm_open("memory_exp1",O_RDWR, mode);
                if (fd == -1)
                        perror("shm_open");
                if (ftruncate(fd, size) == -1)
                        perror("ftruncate");

                struct shmbuf *shmp=(shmbuf*)mmap(NULL,sizeof(*shmp),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
                if(shmp == MAP_FAILED)
                        perror("Struct failed");       
                cout<<"\nEnter the value";
                cin>>strTemp;
                shmp->cnt=100;
                memcpy(&shmp->buf,strTemp,100);
        
                close(fd);
         }
        return 0;
}

错误分析与修复方案

1. 权限冲突与共享内存创建问题

  • Read.cpp首次调用shm_open仅传O_CREAT,缺少O_RDWR标志,导致创建的共享内存无法正常读写,后续ftruncate可能失败。
    修复:修改首次shm_open调用:
    fd=shm_open("memory_exp1",O_CREAT|O_RDWR, mode);
    
  • Write.cpp中shm_open用O_RDONLY打开,但mmap指定PROT_READ|PROT_WRITE,权限不匹配导致映射失败。
    修复:要么将shm_open标志改为O_RDWR,要么将mmap保护位改为PROT_READ(读操作无需写权限)。

2. 内存泄漏问题

  • 两个程序每次循环都调用mmap,但从未调用munmap释放映射内存,最终触发内存耗尽错误。
    修复:每次使用完映射内存后,调用munmap(shmp, sizeof(*shmp))释放资源。
  • Write.cpp中close(fd)放在循环外,每次循环重新打开fd会覆盖旧文件描述符,导致资源泄漏。
    修复:在循环内完成mmap操作后立即close(fd)。

3. 越界访问与逻辑漏洞

  • Write.cpp中若输入非1/2的数值,会继续执行后续代码,若此时shm_open或mmap失败,直接访问shmp会触发段错误。
    修复:在shm_open或mmap失败后,跳过后续读写逻辑,避免访问无效指针。
  • Read.cpp中用memcpy复制字符串未考虑缓冲区大小,可能导致越界。
    修复:改用strncpy并手动添加字符串结束符,确保安全:
    strncpy(shmp->buf, strTemp, sizeof(shmp->buf)-1);
    shmp->buf[sizeof(shmp->buf)-1] = '\0';
    

修复后的示例代码(关键修改版)

修复后的Read.cpp

#include<iostream>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include"headerfile.h"
using namespace std;
int main()
{
        cout<<"point1";
        int fd;
        struct shmbuf *shmp = nullptr;
        const int shm_size = sizeof(struct shmbuf);
        int i=0;
        char strTemp[100]="";
        const int mode = S_IRWXO|S_IRWXG|S_IRWXU;

        // 首次创建并初始化共享内存
        fd=shm_open("memory_exp1",O_CREAT|O_RDWR, mode);
        if (fd == -1) {
                perror("shm_open create");
                return 1;
        }
        if (ftruncate(fd, shm_size) == -1) {
                perror("ftruncate");
                close(fd);
                return 1;
        }
        close(fd);

        while(1)
        {
                cout<<"\nEnter 2 to exit\nto continue press any other value :";
                cin >> i;
                if(i==2)
                        break;

                fd=shm_open("memory_exp1",O_RDWR, mode);
                if (fd == -1) {
                        perror("shm_open");
                        continue;
                }

                shmp=(struct shmbuf*)mmap(NULL, shm_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
                if(shmp == MAP_FAILED) {
                        perror("Struct failed");
                        close(fd);
                        continue;
                }

                cout<<"\nEnter the value";
                cin>>strTemp;
                shmp->cnt=100;
                strncpy(shmp->buf, strTemp, sizeof(shmp->buf)-1);
                shmp->buf[sizeof(shmp->buf)-1] = '\0';

                munmap(shmp, shm_size);
                close(fd);
         }
        // 可选:程序退出时清理共享内存
        shm_unlink("memory_exp1");
        return 0;
}

修复后的Write.cpp

#include<iostream>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include"headerfile.h"
using namespace std;
int main()
{
        int fd;
        struct shmbuf *shmp = nullptr;
        const int shm_size = sizeof(struct shmbuf);
        int i=0;
        while(1)
        {
                cout<<"\nenter 1 to read again and 2 to exit : ";
                cin>>i;
                if(i==2)
                        break;
                if(i!=1) {
                        cout<<"Invalid input, please enter 1 or 2\n";
                        continue;
                }

                fd=shm_open("memory_exp1",O_RDONLY, 0666);
                if (fd == -1) {
                        perror("shm_open");
                        continue;
                }

                shmp = (struct shmbuf*)mmap(NULL, shm_size, PROT_READ, MAP_SHARED, fd, 0);
                if(shmp==MAP_FAILED) {
                        perror("MMap error");
                        close(fd);
                        continue;
                }

                cout <<"\n Read data is: " << shmp->buf << "\n Count: " << shmp->cnt;        

                munmap(shmp, shm_size);
                close(fd);
        }
        return 0;
}

内容的提问来源于stack exchange,提问作者ram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 02:24:30