Стратегии Named Pipe с динамической памятью?

Итак, у меня есть приложение, в котором мне нужен IPC... Я думаю, что именованные каналы — это то, что нужно, потому что они очень просты в использовании.

В любом случае, у меня есть вопрос о том, как обрабатывать динамическую память с использованием именованных каналов.

Скажем, у меня есть такой класс:

class MyTestClass {
public:
    MyTestClass() { _data = new int(4); }

    int GetData() { return *_data; }
    int GetData2() { return _data2; }

private:
    int* _data;
    int _data2;
};

Теперь, когда я создаю буфер, полный MyTestClass объектов, а затем отправляю их по каналу, я, очевидно, теряю _data в целевом процессе и получаю мусор. Есть ли какая-то стратегия, которую я должен использовать? Я могу использовать типы значений для простых случаев, но для многих сложных классов мне нужно использовать некоторую динамическую память, и мне нравятся указатели.

Или я должен вместо этого просто посмотреть на использование общей памяти? Спасибо


person Polaris878    schedule 08.09.2009    source источник
comment
Я думаю, вам следует удалить _data2 и еще много чего. Он не завершен (инициализирован), и я думаю, что ваш вопрос и без него ясен.   -  person GManNickG    schedule 08.09.2009
comment
Поскольку ваш конструктор выделяет память, вам нужен деструктор, чтобы освободить эту память, не так ли?   -  person Jonathan Leffler    schedule 08.09.2009
comment
да, мне нужно его выпустить, извините за дурной тон... Я просто хотел донести суть   -  person Polaris878    schedule 08.09.2009


Ответы (2)


Именованные каналы, и разделяемая память имеют схожие проблемы: вам необходимо сериализовать содержимое структуры на стороне отправки и десериализовать структуру на стороне получателя.

Процесс сериализации практически идентичен независимо от того, используете ли вы именованные каналы или разделяемую память. Для встроенных указателей (таких как _data и _data2) вам необходимо последовательно сериализовать содержимое указателя.

Существует множество стратегий сериализации, которые вы можете использовать, в зависимости от того, как ваши структуры расположены в памяти и насколько эффективным должен быть ваш IPC. Или вы можете использовать DCE RPC и позволить коду маршалинга RPC справиться со всеми сложностями за вас.

person ReinstateMonica Larry Osterman    schedule 08.09.2009
comment
Спасибо за ответ ... какие-нибудь советы по протоколам, которые я мог бы использовать, или стратегиям сериализации, которые я мог бы использовать? Спасибо - person Polaris878; 08.09.2009
comment
Если вы ищете стратегии сериализации, наиболее распространенным случаем является хранение файлов. Как бы вы записали свой класс в файл и прочитали его позже? Возможно, вы сможете сэкономить много работы, если обернете свой канал IPC как std::streambuf; таким образом вы можете делиться и повторно использовать большой объем кода. - person MSalters; 08.09.2009
comment
MSalters взял слова прямо из моего рта. Его предложение в точку. - person ReinstateMonica Larry Osterman; 09.09.2009

Чтобы отправить данные по именованному каналу, вы должны сериализовать (или маршалировать) данные на передающей стороне и десериализовать (или демаршалировать) их на принимающей стороне.

Звучит подозрительно, как будто вы просто записываете копию байтов в структуру данных. Это никуда не годится. Вы не копируете выделенные данные (они хранятся не между первым и последним байтами структуры данных, а вообще куда-то еще), и вы копируете указатель (_data) с одной машины (или процесса) на другую, и адрес памяти в локальном процессе не имеет гарантированного значения в другом.

Определите себе проводной протокол (если отчаянно, посмотрите на ASN.1 - нет, если подумать, не впадайте в отчаяние), который определяет структуру данных для передачи по проводу. Затем реализуйте функции отправителя и получателя (или сериализатора и десериализатора). Или найдите чужой код, который уже делает это.

Также не забудьте разобраться с порядком байтов — вы должны определить, в какой последовательности байты отправляются через именованный канал.

Например, вы можете определить, что отправленное сообщение состоит из 4-байтового целого числа без знака в сетевом порядке байтов, определяющем, сколько структур следует за ним, и каждая структура может быть последовательностью из 4 4-байтовых целых чисел со знаком для массива, за которыми следует один знаковый 4-байтовое целое число для _data2 (также отправляется в сетевом порядке байтов).

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

person Jonathan Leffler    schedule 08.09.2009
comment
Спасибо... Вот о чем я думал... Я немного новичок в IPC. Прямо сейчас я просто отправлял необработанные байты через ха-ха ... Я хотел посмотреть, каковы пределы этих механизмов IPC. Вы на 100% правы в том, что байтов нет в структуре данных... это именно та проблема, которую я пытался решить. - person Polaris878; 08.09.2009