сбой очереди сообщений boost при отправке строки

Я пытаюсь передать строковое содержимое другому процессу, используя boost interprocess message_queue. У меня нет проблем, когда я передаю целые числа, но когда я хочу передать буфер, лежащий в основе std::string, возникает исключение

boost::interprocess_exception::library_error

Код ниже. Что может быть причиной этого сбоя?

  // SENDER process
  //
  message_queue::remove("messagequeue");

  //Create a message_queue.
  message_queue mq (create_only,"messagequeue",100,sizeof(char));
  std::string text("ciao");
  mq.send(text.data(), text.size(), 0);
  sleep(100);


  // RECV process
  //
  void get()
  {
    message_queue mq(open_only,"messagequeue");
    unsigned int priority;
    message_queue::size_type recvd_size;

    std::string message;
    message.resize(100);
    mq.receive(&message[0], 100, recvd_size, priority);
    message.resize(recvd_size);
    std::cout << message << std::endl;

    sleep(100000);
  }

  int main()
  {
    boost:: thread t;
    t = boost::thread(get);
    t.join();
    return 1;
  }

person Abruzzo Forte e Gentile    schedule 22.09.2016    source источник
comment
Я думаю, что может быть несколько проблем с вашим кодом. Отправка text.size() не отправляет завершающий ноль. Я бы также избегал использования конструкции message[0] при получении. Если вы хотите сделать это, используйте вместо этого вектор. .data() тоже чище. Не забывайте о завершающем нуле, когда вы также переводите вектор в строку.   -  person Adrian Roman    schedule 22.09.2016
comment
такая же проблема. Ничего не изменилось. Ниже моего кода. std::vector‹char› данные; data.push_back('с'); data.push_back('я'); data.push_back('а'); data.push_back('о'); data.push_back('\n'); mq.send(data.data(), data.size(), 0);   -  person Abruzzo Forte e Gentile    schedule 22.09.2016
comment
@AdrianRoman нет завершающего NUL (по крайней мере, значимого, тот, который добавляет std::string, предназначен исключительно для устаревшего взаимодействия). На самом деле внутри строки может быть много NUL-символов.   -  person sehe    schedule 23.09.2016
comment
Это верно и не имеет значения. Вы все равно можете переполнить буфер, если будете обращаться следующим образом: &message[0]. Lakeweb дал правильный ответ. Я просто бегло просмотрел код и заметил использование адресов, что может быть опасно. Здесь такого не было, проблема была в другом.   -  person Adrian Roman    schedule 24.09.2016


Ответы (1)


Когда вы создаете очередь сообщений, у вас есть sizeof( char ), но вы пытаетесь поместить 4 символа в буфер. Трассировка поносит исключение по адресу:

   if (buffer_size > p_hdr->m_max_msg_size) {
      throw interprocess_exception(size_error);
   }

В message_queue.hpp. С участием:

bi::message_queue mq( bi::open_or_create,"messagequeue", 100, 4 );

это работает для "чао".

person lakeweb    schedule 22.09.2016
comment
Он может быть заполнен или не заполнен терминатором NUL. Несмотря на это, std::cout << s;, скорее всего, просто реализовано как std::cout.write(s.data(), s.size()). Никогда не задействован терминатор NUL. Речь идет о размере, а не о стражах в C++ - person sehe; 23.09.2016
comment
Здравствуйте, в соответствии с этим буфер будет заполнен нулевыми символами на a 'string::resize', в то время как межпроцессный процесс просто выполнит memcpy полезной нагрузки. При этом второй ресайз не понадобился. Я думаю, вы неправильно поняли, что я имел в виду, или я не понимаю. - person lakeweb; 24.09.2016
comment
ciao не печатает без завершающих символов, потому что буфер обнулен. Он печатает без завершающих символов, потому что длина строки составляет 5 байтов (он не будет печатать конечный мусор, даже если изменение размера не обнулит буфер) - person sehe; 24.09.2016
comment
А, теперь я понял. потому что xsputn использует размер строки или нулевой символ, что наступит раньше. Спасибо. - person lakeweb; 24.09.2016
comment
Эм. Неа. Он не использует нулевой символ . Даже cplusplus.com получил это прямо на странице, на которую вы ссылаетесь. Изменить: доказательство пудинга - person sehe; 24.09.2016
comment
Привет, сехе, мой мозг, должно быть, действительно хотел иметь отношение к этому нулевому терминатору, поэтому я пропускаю чтение ссылки. Я удалил это обновление, так как оно неправильное. Еще раз спасибо. - person lakeweb; 24.09.2016
comment
Ах ах! Большое тебе спасибо! Я неправильно понял смысл последнего аргумента. Я думал, что boost IPC выделит в 100 раз больше char и тогда я буду писать туда как в буфер. Вместо этого значение имеет размер одной записи. Спасибо большое за помощь. Очень признателен! Лучший - person Abruzzo Forte e Gentile; 28.09.2016