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

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

本文关键字:读取 字符串 c++ SHM IPC      更新时间:2023-10-16

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

共享记忆.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; 
}
};

在外面,我像这样使用它:

发件人.cpp

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

接收器.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);
}

字符串流 ss 在您的函数中没有任何功能用途,除了添加错误。 我建议你试试这个:

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 引用传递的,这是为了避免复制它们(以及与那些不需要的内存分配相关的潜在错误(