Почему возникла ошибка zmq, если задано значение сериализуемого класса protobuf? - PullRequest
0 голосов
/ 25 июня 2018

Я тестирую код, использующий zmq в качестве сокета и сетевого инструмента, и protobuf для сериализации.

Код получает zmq_message и анализирует его в классе protobuf, взамен я изменяю значение одного из членов класса и отправляю тот же класс обратно запрашивающей стороне.

Каким-то образом во время этого процесса утверждение zmq check() не выполняется. Я действительно не знаю, почему это происходит, поскольку все выглядит хорошо для меня.

Код выглядит в основном файле следующим образом:

zmq::socket_t external(context, ZMQ_REP);
external.bind("tcp://*:29067");

zmq::message_t request;
external.recv(&request);
msg.deserialize(request);

msg.set_probed_value(12.0);
zmq::message_t response = msg.serialize();
external.send(response);

метод десериализации выглядит следующим образом.

_msg.ParseFromString(reinterpret_cast<const char*>(msg.data()));

и метод сериализации, как показано ниже:

zmq::message_t request(_msg.ByteSize());
std::string value = _msg.SerializeAsString();
memcpy(request.data(), reinterpret_cast<const void*>(value.c_str()), value.size());
return request;

и set_probed_value() выглядит так:

void set_probed_value(const double& val)
{
    _msg.clear_probed();
    _msg.set_probed(val);
}

Я точно знаю, что проблема возникает, когда я устанавливаю значение зонда на другое значение, отличное от того, которое было установлено во время разбора. Если я уберу эту строку msg.set_probed_value(12.0), исключений не будет, и все в порядке.

Утверждение не удалось: check () (/apps/zmq/libzmq/src/msg.cpp:347)

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Вы уверены, что в этом сообщении zmq msg есть завершение NULL?

_msg.ParseFromString(reinterpret_cast<const char*>(msg.data()));

Если нет, это заполнит ваш _msg мусором, так как он читает после конца то, что вы считаете строкой.

Причина, по которой я спрашиваю::

При создании / отправке сообщения вы не включаете NULL

zmq::message_t request(_msg.ByteSize());
std::string value = _msg.SerializeAsString();
memcpy(request.data(), reinterpret_cast<const void*>(value.c_str()), value.size());
return request;
0 голосов
/ 25 июня 2018

Подозреваемый? Нарушение опубликованных принципов API ZeroMQ

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

Как насчет того, чтобы сначала сделать явную копию контента, вместо простого синтаксического подслащенного reinterpret_cast<...>( msg.data() ) контента (на который ссылается поставляемый указатель ZeroMQ), которым непосредственно манипулируют?

Избегайте изменения содержимого сообщения после того, как сообщение было скопировано с помощью zmq_msg_copy(), это может привести к неопределенному поведению . Если вам нужна настоящая печатная копия, выделите новое сообщение, используя zmq_msg_init_size(), и скопируйте содержимое сообщения, используя memcpy().

.

Также рекомендуется явно указывать close() объекта сообщения request сразу после создания безопасной копии содержимого, как настоятельно рекомендует опубликованная добросовестная практика проектирования в опубликованном API ZeroMQ.

Никогда не обращайтесь к zmq_msg_t членам напрямую, вместо этого всегда используйте семейство функций zmq_msg.

API ZeroMQ явно предупреждает, чтобы не пытаться манипулировать каким-либо содержимым сообщения любым другим способом, кроме использования функций / методов, опубликованных API. Лучше избегать подобных уловок, даже за счет немного более длинного кода и нескольких SLOC-ов.

...