मैं एक कोड का परीक्षण कर रहा हूं जो zmq को सॉकेट और नेटवर्किंग टूल के रूप में उपयोग करता है, और क्रमांकन के लिए प्रोटोबफ का उपयोग करता है।

कोड एक zmq_message प्राप्त करता है और इसे प्रोटोबफ वर्ग में पार्स करता है, बदले में मैं कक्षा के सदस्यों में से एक का मान बदलता हूं और उसी वर्ग को अनुरोधकर्ता को वापस भेजता हूं।

किसी तरह इस प्रक्रिया के दौरान एक 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);

Deserialize विधि इस तरह दिखती है।

_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) को हटा दूं, तो कोई अपवाद नहीं होगा और सब कुछ ठीक है।

दावा विफल: चेक () (/apps/zmq/libzmq/src/msg.cpp:347)

0
apramc 25 जून 2018, 16:41

2 जवाब

सबसे बढ़िया उत्तर

संदिग्ध? ज़ीरोएमक्यू एपीआई प्रकाशित सिद्धांतों का उल्लंघन

सभी संदेश जोड़तोड़ काफी नाजुक माने जाते हैं।

एक स्पष्ट सामग्री-प्रतिलिपि करने के बारे में पहले, केवल सिंटैक्स शर्करायुक्त reinterpret_cast<...>( msg.data() ) सामग्री (ज़ीरोएमक्यू डिलीवर पॉइंटर द्वारा संदर्भित) के बजाय सीधे छेड़छाड़ की जा रही है?

zmq_msg_copy() के साथ किसी संदेश की प्रतिलिपि बनाने के बाद संदेश सामग्री को संशोधित करने से बचें, ऐसा करने से अपरिभाषित व्यवहार हो सकता है। यदि आपको एक वास्तविक हार्ड कॉपी चाहिए, तो zmq_msg_init_size() का उपयोग करके एक नया संदेश आवंटित करें और memcpy() का उपयोग करके संदेश सामग्री की प्रतिलिपि बनाएँ।

सुरक्षित सामग्री-प्रतिलिपि बनाए जाने के ठीक बाद, request संदेश वस्तु के स्पष्ट close() की भी सलाह दी जाती है, जैसा कि प्रकाशित ज़ीरोएमक्यू एपीआई में प्रकाशित निष्पक्ष डिजाइन अभ्यास दृढ़ता से अनुशंसा करता है।

कभी भी zmq_msg_t सदस्यों को सीधे एक्सेस न करें, इसके बजाय हमेशा zmq_msg फंक्शन्स के परिवार का उपयोग करें।

ज़ीरोएमक्यू एपीआई स्पष्ट रूप से चेतावनी दे रहा है कि किसी भी संदेश सामग्री में हेरफेर करने का प्रयास न करें एपीआई-प्रकाशित कार्यों / विधियों का उपयोग करने के अलावा किसी अन्य तरीके से। थोड़ा अधिक लंबा कोड और कुछ और एसएलओसी-एस की कीमत पर भी ऐसी किसी भी चाल से बचें।

1
user3666197 25 जून 2018, 19:13

क्या आप सुनिश्चित हैं कि आपके पास उस zmq संदेश msg में एक पूर्ण समाप्ति है?

_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
James Harvey 27 जून 2018, 15:02