Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ ZeroMQ socket.recv()引发堆栈溢出异常_C++_Windows_Zeromq - Fatal编程技术网

C++ ZeroMQ socket.recv()引发堆栈溢出异常

C++ ZeroMQ socket.recv()引发堆栈溢出异常,c++,windows,zeromq,C++,Windows,Zeromq,如果在.dll中使用此代码,调用socket.recv()会引发异常堆栈溢出,但当此代码编译为.exe时,它会工作 为什么? 我通过“C:\windows\system32\rundll32.exe myDll.dll启动程序”运行一个.dll-测试 调用堆栈: libzmq-v120-mt-gd-4_2_2.dll!zmq::mailbox_t::recv(zmq::command_t * cmd_=0x0231f700, int timeout_=0x00000000) libzmq-v

如果在
.dll
中使用此代码调用
socket.recv()
会引发异常
堆栈溢出
,但当此代码编译为
.exe
时,它会工作

为什么?

我通过“
C:\windows\system32\rundll32.exe myDll.dll启动程序”
运行一个
.dll
-测试

调用堆栈:

libzmq-v120-mt-gd-4_2_2.dll!zmq::mailbox_t::recv(zmq::command_t * cmd_=0x0231f700, int timeout_=0x00000000) 

libzmq-v120-mt-gd-4_2_2.dll!zmq::io_thread_t::in_event() 

libzmq-v120-mt-gd-4_2_2.dll!zmq::select_t::loop() 

libzmq-v120-mt-gd-4_2_2.dll!zmq::select_t::worker_routine(void * arg_=0x002f1778) 
libzmq-v120-mt-gd-4_2_2.dll!thread_routine(void * arg_=0x002f17c0) 
主线程调用堆栈:

libzmq-v120-mt-gd-4_2_2.dll!zmq::signaler_t::wait(int timeout_=0xffffffff)
libzmq-v120-mt-gd-4_2_2.dll!zmq::mailbox_t::recv(zmq::command_t * cmd_=0x0019f3c0, int timeout_=0xffffffff) 
libzmq-v120-mt-gd-4_2_2.dll!zmq::socket_base_t::process_commands(int timeout_, bool throttle_)
libzmq-v120-mt-gd-4_2_2.dll!zmq::socket_base_t::recv(zmq::msg_t * msg_=0x0019f628, int flags_=0x00000000)
libzmq-v120-mt-gd-4_2_2.dll!s_recvmsg(zmq::socket_base_t * s_=0x006f6c70, zmq_msg_t * msg_=0x0019f628, int flags_=0x00000000) 
libzmq-v120-mt-gd-4_2_2.dll!zmq_msg_recv(zmq_msg_t * msg_=0x0019f628, void * s_=0x006f6c70, int flags_=0x00000000)
mydll.dll!zmq::socket_t::recv(zmq::message_t * msg_=0x0019f628, int flags_=0x00000000)
mydll.dll!StartUp() 

更新: 这个例子也因为同样的原因崩溃了。有人知道异常堆栈溢出的原因吗

zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REP);

socket.bind("tcp://*:7712");

while (1){
    Sleep(10);
}

反向问题隔离MCVE: 这个
myDll.dll
-test
是如何工作的,
如果由
C:\windows\system32\rundll32.exe myDll.dll启动运行
?张贴屏幕输出

void StartUp()
{
     std::cout << "INF:: ENTRY POINT ( C:\windows\system32\rundll32.exe myDll.dll StartUp )" << std::endl;
     std::cout << "INF:: WILL SLEEP  ( C:\windows\system32\rundll32.exe myDll.dll StartUp )" << std::endl;
     Sleep( 10 );
     std::cout << "INF:: SLEPT WELL  ( C:\windows\system32\rundll32.exe myDll.dll StartUp )" << std::endl;
     std::cout << "INF:: WILL RETURN ( C:\windows\system32\rundll32.exe myDll.dll StartUp )" << std::endl;
}
void启动()
{
std::cout ZeroMQ对象需要某些方面才能使用:
正如你在屏幕上已经看到的那样,雷达下有很多功能,可能会造成灾难性的破坏

最好注意适当的读,同时使用ZrOMQ C++绑定参考文档加上原始的ZrOMQ API(这也是C++绑定中经常提到的)。

两个都强调,不直接处理<代码> ZMQ::MeaseGytwhile(true){…}中的

zmq::message\u t message;
构造函数生成
-循环,其中任何一个都没有遇到它自己的公平析构函数。堆栈的物理容量有限,并且DLL内部没有堆栈管理,迟早会失败

zmq::message\u t
实例是一个非常昂贵的玩具,因此对于专业代码来说,良好的资源管理实践(预分配、重用、受控销毁)总是受欢迎的

Q.E.D


为清楚起见,尾语: 对Dijkstra关于错误搜索和软件测试的观点进行了一点解释:“如果我没有看到错误,这并不意味着代码中没有错误(如果除了它之外还有任何外部函数链接,那么代码中就没有错误了)。”

没有堆栈分配

是,没有可见的。

ZeroMQ API为其带来了更多亮点:

“zmq_msg_init_size()
函数应分配存储消息大小字节所需的任何资源,并初始化消息引用的消息对象,以表示新分配的消息

实现应选择是将消息内容存储在堆栈上(小消息)还是堆上(大消息)。出于性能原因,
zmq_msg_init_size()
不应清除消息数据。”

多年来,我一直在使用基于ZeroMQ API(自v.2.1+以来)的跨平台分布式系统,这让我学到了很多关于显式资源控制的注意事项。还有一次,你没有为本机API开发自己的语言绑定


在所有不受支持的批评之后,让我们再添加一条来自ZeroMQ的引文:

这增加了一个视图,如何正确地间接操纵<代码> MasaGigt 内容由库C++绑定本身完成,包为琐碎的帮助函数:

zhelpers.hpp

//从套接字接收0MQ字符串并转换为字符串
静态std::string
s_recv(zmq::插座和插座){
zmq::消息\u t消息;
socket.recv(&message);
返回std::string(static_cast(message.data()),message.size());
}
//将字符串转换为0MQ字符串并发送到套接字
静态布尔
s_发送(zmq::socket\u t&socket,const std::string&string){
消息(string.size());
memcpy(message.data(),string.data(),string.size());
bool rc=socket.send(消息);
返回(rc);
}
//将字符串作为0MQ字符串发送,作为多部分非终端
静态布尔
s_sendmore(zmq::socket\u t&socket,const std::string&string){
消息(string.size());
memcpy(message.data(),string.data(),string.size());
bool rc=socket.send(消息,ZMQ_SNDMORE);
返回(rc);
}
ZeroMQ对象需要某些方面才能使用: 正如你在屏幕上已经看到的那样,雷达下有很多功能,可能会造成灾难性的破坏

最好注意适当的读,同时使用ZrOMQ C++绑定参考文档加上原始的ZrOMQ API(这也是C++绑定中经常提到的)。

两个都强调,不直接处理<代码> ZMQ::MeaseGytwhile(true){…}中的

zmq::message\u t message;
构造函数生成-循环,其中任何一个都没有遇到它自己的公平析构函数。堆栈的物理容量有限,并且DLL内部没有堆栈管理,迟早会失败

zmq::message\u t
实例是一个非常昂贵的玩具,因此对于专业代码来说,良好的资源管理实践(预分配、重用、受控销毁)总是受欢迎的

Q.E.D


为清楚起见,尾语: 对Dijkstra关于错误搜索和软件测试的观点进行了一点解释:“如果我没有看到错误,这并不意味着代码中没有错误(如果除了它之外还有任何外部函数链接,那么代码中就没有错误了)。”

没有堆栈分配

是,没有可见的。

ZeroMQ API为其带来了更多亮点:

“zmq_msg_init_size()函数应分配存储消息大小字节所需的任何资源,并初始化消息引用的消息对象,以表示新分配的消息

实施sha
void StartUp()
{
     std::cout << "INF:: ENTRY POINT ( C:\windows\system32\rundll32.exe myDll.dll StartUp )" << std::endl;
     std::cout << "INF:: WILL SLEEP  ( C:\windows\system32\rundll32.exe myDll.dll StartUp )" << std::endl;
     Sleep( 10 );
     std::cout << "INF:: SLEPT WELL  ( C:\windows\system32\rundll32.exe myDll.dll StartUp )" << std::endl;
     std::cout << "INF:: WILL RETURN ( C:\windows\system32\rundll32.exe myDll.dll StartUp )" << std::endl;
}
zmq::message_t messageIN,
               messageOUT;

bool successFlag;

while (true){

             successFlag  = socket.recv( &messageIN );
     assert( successFlag && "EXC: .recv( &messageIN )" );
                        /* The zmq_recv() function shall receive a message
                           from the socket referenced by the socket argument
                           and store it in the message referenced by the msg
                           argument.
                           Any content previously stored in msg shall be
                           properly deallocated.
                           If there are no messages available on the specified
                           socket the zmq_recv() function shall block
                           until the request can be satisfied.
                           */

                       messageOUT.copy(  messageIN );

             successFlag  = socket.send(  messageOUT );
     assert( successFlag && "EXC: .send(  messageOUT )" );
                        /* The zmq_send() function shall queue the message
                           referenced by the msg argument to be sent to
                           the socket referenced by the socket argument.
                           The flags argument is a combination of the flags
                           defined { ZMQ_NOBLOCK, ZMQ_SNDMORE }

                           The zmq_msg_t structure passed to zmq_send()
                           is nullified during the call.

                           If you want to send the same message to multiple
                           sockets you have to copy it using (e.g.
                           using zmq_msg_copy() ).

                           A successful invocation of zmq_send()
                           does not indicate that the message
                           has been transmitted to the network,
                           only that it has been queued on the socket
                           and ØMQ has assumed responsibility for the message.
                           */
};
//  Receive 0MQ string from socket and convert into string
static std::string
s_recv (zmq::socket_t & socket) {

    zmq::message_t message;
    socket.recv(&message);

    return std::string(static_cast<char*>(message.data()), message.size());
}

//  Convert string to 0MQ string and send to socket
static bool
s_send (zmq::socket_t & socket, const std::string & string) {

    zmq::message_t message(string.size());
    memcpy (message.data(), string.data(), string.size());

    bool rc = socket.send (message);
    return (rc);
}

//  Sends string as 0MQ string, as multipart non-terminal
static bool
s_sendmore (zmq::socket_t & socket, const std::string & string) {

    zmq::message_t message(string.size());
    memcpy (message.data(), string.data(), string.size());

    bool rc = socket.send (message, ZMQ_SNDMORE);
    return (rc);
}