Очередь в разделяемой памяти, ведущая вверх - PullRequest
0 голосов
/ 13 декабря 2011

Общая память доставляет мне неприятности, и GDB не сильно помогает. У меня выделено 32 КБ общей памяти, и я использовал shmat для приведения ее к указателю на struct, содержащую A) a bool и B) очередь объектов, содержащих одну std::string, три int s и один bool, плюс разные методы. (Я не знаю, должна ли эта структура matryoshka, как вы должны это делать, но это единственный способ, который я знаю. Использование очереди сообщений не вариант, и мне нужно использовать несколько процессов.)

Нажатие одного объекта в очередь работает, но когда я пытаюсь нажать второй, программа зависает. Нет сообщения об ошибке, нет ничего. Что вызывает это? Я сомневаюсь, что это нехватка памяти, но если это так, сколько мне нужно?

РЕДАКТИРОВАТЬ: В случае, если мне было неясно - объекты в очереди относятся к классу с пятью описанными членами данных.

РЕДАКТИРОВАТЬ 2: Я изменил класс записей очереди, чтобы он не использовал std::string. (Довольно неловко, я смог представить данные примитивом.) Программа все еще зависает при втором нажатии ().

РЕДАКТИРОВАТЬ 3: Я пытался вызвать front() из той же очереди сразу после первой push(), и it также заморозило программу. Однако проверка значения bool за пределами очереди работала нормально, поэтому с самой очередью должно быть что-то не так.

РЕДАКТИРОВАТЬ 4: В качестве эксперимента я добавил std::queue<int> к struct, который я использовал для общей памяти. Он показал то же самое поведение - push() работал один раз, затем front() заставляло его зависать. Так что это не проблема с классом, который я использую для элементов очереди.

Этот вопрос предполагает, что я вряд ли смогу решить эту проблему с помощью std::queue. Это так? Должен ли я использовать boost, как написано? (В моем случае я выполняю shmget() и shmat() в родительском процессе и пытаюсь позволить двум дочерним процессам взаимодействовать, так что это немного отличается.)

РЕДАКТИРОВАТЬ 5: Другой дочерний процесс также останавливается при вызове front(). Семафор гарантирует, что это произойдет после первого push() вызова.

Ответы [ 2 ]

5 голосов
/ 13 декабря 2011

Помещение std::string объектов в сегмент общей памяти не может возможно работать.

Он должен нормально работать для одного процесса, но как только вы попытаетесь получить к нему доступ из второго процесса, вы получите мусор: строка будет содержать указатель на данные, выделенные в куче, и этот указатель будет только действует в процессе, который его выделил.

Я не знаю, почему ваша программа зависает, но это совершенно бессмысленно даже думать о.

1 голос
/ 13 декабря 2011

Как я уже говорил в своем комментарии, ваша проблема связана с попыткой использовать объекты, которые внутренне требуют выделения кучи в структуре, которая должна быть автономной (то есть не требует дополнительной динамически выделяемой памяти).

Я бы настроил вашу настройку и изменил бы std :: string на некоторый массив символов фиксированного размера, что-то вроде

// this structure fits nicely into a typical cache line
struct Message
{
  boost::array<char, 48> some_string;
  int a, b, c;
  bool c;
};

Теперь, когда вам нужно что-то опубликовать в очереди, скопируйте содержимое строки в some_string. Конечно, вы должны подходить по размеру для ваших строк (и boost::array, вероятно, не самый лучший - в идеале, вы также хотите получить некоторую информацию о длине), но вы поняли ...

...