在 C++ 中写入 IPC SHM 时无法读取完整的字符串

Can't read complete string when writing into IPC SHM in c++

我正在尝试构建一个简单的界面以在 C++ 中使用 shm ipc。为此,我编写了以下代码:

sharedmem.h:

#pragma once

#include <iostream> 
#include <sstream> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <stdio.h> 
using namespace std;

namespace IPC
{
    void Send(const string filename, std::string msg,int size=1024 )
    {
        key_t key = ftok(filename.c_str(),65); 
        std::stringstream ss;
        ss << msg.c_str();
        int shmid = shmget(key,size,0666|IPC_CREAT); 

        char *str = (char*) shmat(shmid,(void*)0,0); 
        ss >> str; 

        shmdt(str); 
    }

    string Receive(const string filename, int size=1024 )
    {
        key_t key = ftok(filename.c_str(),65); 
        int shmid = shmget(key,size,0666|IPC_CREAT); 
        char *str = (char*) shmat(shmid,(void*)0,0); 
        string ret(str);
        shmdt(str); 
        shmctl(shmid,IPC_RMID,NULL); 

        return ret; 
    }
};

在外面,我这样用:

sender.cpp

#include "sharedmem.h"
int main() 
{ 
    IPC::Send("fila1", "hello ipc");

    return 0;
} 

receiver.cpp

#include "sharedmem.h"
int main() 
{ 
    std::string ret = IPC::Receive("fila1");
    cout << "Recebi na fila: " << ret;

    return 0;
} 

CMakeLists.txt:

set (CMAKE_CXX_STANDARD 17)

add_executable(sender sender.cpp)
add_executable(receiver receiver.cpp)

并使用 cmake . && make

构建

在这个例子中我写 "hello ipc" 但另一个进程只读 "hello"。这里有什么问题?提前致谢。

在您的发送函数中:

void Send(const string filename, std::string msg,int size=1024 )
{
    key_t key = ftok(filename.c_str(),65); 
    std::stringstream ss;
    ss << msg.c_str();

    int shmid = shmget(key,size,0666|IPC_CREAT);  // this call could fail, what happens next is 
                                                  // a likely a segmentation error.
                                                  // ...  or worse.
    char *str = (char*) shmat(shmid,(void*)0,0); 

    ss >> str;  // <-- error is here.  You extract from ss until the first whitespace character.
                // what happens if input string is larger than the size of the allocated block?

    shmdt(str);
}

stringstream ss在你的函数中没有任何作用,除了添加一个bug。我建议你试试这个:

int Send(const string& filename, const std::string& msg) noexcept // if you have no return value, 
                                                          // you should throw on error, 
                                                          // let's avoid that
{
    key_t key = ftok(filename.c_str(), 65); // you should maybe consider using a named constant 
                                            // for your project ID
    if (key == -1)
        return errno;

    int shmid = shmget(key, msg.length() + 1, 0666 | IPC_CREAT);  // allocate enough memory for the 
                                                                  // message, plus its NULL terminator
    if (shmid == -1)
        return errno;

    void *shared_mem = shmat(shmid, nullptr, 0); 
    if (shared_mem == (void*)-1)
    {
         //  the systeml failed to lock the allocated memory.  
         //  do some cleanup by de-allocating the shared memory block.
         int ret = errno; // keep original error for return.
         shmctl(shmid , IPC_RMID, nullptr);
         return ret;
    }

    // copy message string with its NULL terminator to shared memory
    memcpy(shared_mem, msg.c_str(), msg.length() + 1); // using length() + 1 is ok here, result of 
                                                       // c_str() always has a NULL terminator.
    shmdt(shared_mem);
    return 0;
}

您的接收函数也缺少错误检查。这应该与 Send() 函数非常相似。

请注意,字符串是通过 const 引用传递的,这是为了避免复制它们(以及与那些不需要的内存分配相关的潜在错误)