Не могу прочитать полную строку при записи в IPC SHM на c ++ - PullRequest
0 голосов
/ 22 сентября 2019

Я пытаюсь создать простой интерфейс для использования shm ipc в c ++.Для этого я написал следующий код:

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;
} 

receive.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

В этомНапример, я пишу "привет IPC", но другой процесс читает только "привет".Что здесь может быть не так?Заранее спасибо.

1 Ответ

2 голосов
/ 23 сентября 2019

В вашей функции отправки:

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 ().

Обратите внимание, что строки передаются по константной ссылке, чтобы избежать их копирования (и потенциальных ошибок, связанных с этими ненужными выделениями памяти)

...