Храните больше данных в iov в C++

Я пишу программу на C++ (см. Ниже). Моя цель - хранить данные в структуре iov. Я выделил буфер фиксированной длины в конструкторе. Каждый раз, когда этот буфер заполняется, я хочу передать данные в iov и выделить новый буфер фиксированной длины. Наконец, когда закончится обработка данных, я хочу вернуть iov struct. Мое намерение здесь состоит в том, чтобы сохранить все эти данные в iov, чтобы, если это потребуется в будущем, я мог легко отправлять данные. Я написал пример кода. Но, похоже, это не работает. Я получил "Ошибка шины: 10". Кто-нибудь может мне помочь?

Образец кода:

#include <iostream>
#include <string>
#include <sys/uio.h>
#include <cstdlib>

using namespace std;
#define MAX_LEN 1000
#define MIN_LEN    20

class MyClass
{   
    public:
        MyClass();
       ~MyClass();
        void fillData(std::string &data);

    private:
       struct iovec     *iov;
       unsigned int     count;
      unsigned int  len;
      char *buf;
      unsigned int total_len;
      unsigned int tmp_len;
};  

MyClass::MyClass()
{   
  cout << "Inside constructor" << endl;
   total_len = MIN_LEN;
   buf = (char *)malloc(MAX_LEN);
   if (buf == NULL) {
        cout << "Error: can’t allocate buf" << endl;
        exit(EXIT_FAILURE);
     } 
}   


MyClass::~MyClass()
{   
    free(buf);
}   

void MyClass::fillData(std::string &data)
{   
    unsigned int d_len, tmp_len, offset;
    d_len = data.size();
    const char* t = data.c_str();
    total_len += d_len;
    tmp_len += d_len;
    if (total_len > MAX_LEN) {

        /* Allocate memory and assign to iov */
        tmp_len = d_len;

     }


    memcpy(buf + offset, t,  d_len);
    /* Adjust offset */
}

int main()
{

  MyClass my_obj;
  int i;
  std::string str = "Hey, welcome to my first class!";
  for (i = 0; i < 10; i++) {
    my_obj.fillData(str);
  }
  return 0;
}

1 ответ

Решение

Не понимая цели вашей программы в деталях, очень ясно, что вы забыли зарезервировать память для iov-объекты сами. Например, в вашем конструкторе вы пишете iov[0].iov_base = buf, еще iov не был выделен ранее.

Чтобы преодолеть это, где-то в вашем коде, перед первым доступом к iov, вы должны написать что-то вроде iov = calloc(100,sizeof(struct iovev)) или эквивалент C++ с использованием new[],

Рассмотрим следующую программу:

struct myStruct {
  char *buf;
  int len;
};

int main() {

  struct myStruct *myStructPtr;

  myStructPtr->buf = "Herbert";  // Illegal, since myStructPtr is not initialized; So even if "Herbert" is valid, there is no place to store the pointer to literal "Herbert".
  myStructPtr[0].buf = "Herbert"; // Illegal, since myStructPtr is not initialized

  // but:
  struct myStruct *myStructObj = new (struct myStruct);
   myStructObj->buf = "Herbert"; // OK, because myStructObj can store the pointer to literal "Herbert"
   myStructObj->buf = "Something else"; // OK; myStructObj can hold a pointer, so just let it point to a different portion of memory. No need for an extra "new (struct myStruct)" here
}

Я взял твой код, который ничего не использовал с iovec, и я немного изменил его.

Я не уверен, почему разработчики предпочитают буферы char* вместо std::stringили зачем использовать указатель, который должен быть выделен и затем удален вместо использования std::vector

Я также добавил функцию, которая использует iovec. Это называется void MyClass::print_data(), Он печатает все данные в векторе iovecs

#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/uio.h>

using namespace std;

class MyClass
{
        vector<struct iovec> iovs;
        vector<string> bufs;
public:
        MyClass();
        ~MyClass();
        void fill_data(const string &data);
        void print_data();
};

MyClass::MyClass()
{
        cout << "Inside constructor" << endl;
}


MyClass::~MyClass()
{
}

void MyClass::fill_data(const string &data)
{
        stringstream stream;
        stream << setw(2) << setfill(' ') << (this->bufs.size() + 1) << ". "
                 << data << endl;
        this->bufs.push_back(stream.str());
        iovec iov = {&(bufs.back()[0]), bufs.back().size()};
        this->iovs.push_back(iov);
}

void MyClass::print_data() {
        writev(STDOUT_FILENO, iovs.data(), iovs.size());
}

int main() {
        MyClass my_obj;
        string str = "Hey, welcome to my first class!";
        for (int i = 0; i < 10; ++i) {
                my_obj.fill_data(str);
        }

        my_obj.print_data();
        return 0;
}

скомпилируйте это так: g++ test.cpp

Другие вопросы по тегам