简体   繁体   English

C ++:堆栈不会在引发异常时解开

[英]C++: Stack is not unwound on exception thrown

Hallo, 哈o

I have a quite strange problem in one of my C++ projects: I wrote a C++ Socket wrapper, that tries to connect to a given host and port (via IPv4/TCP) and throws a SocketException (derived from std::runtime_error), if an error occurs (eg 'Connection refused'). 在我的一个C ++项目中,我遇到了一个非常奇怪的问题:我写了一个C ++套接字包装器,该包装器试图连接到给定的主机和端口(通过IPv4 / TCP),并抛出SocketException(源自std :: runtime_error),如果发生错误(例如“连接被拒绝”)。 The exception is caught properly and an error message is written to console as expected, but apparently the destructor of my Socket class is not called (it should output a message to std::cerr, too, but the message only appears if connection works and Socket is destroyed later on if it goes out of stack, eg on end of the function that tries to utilize the socket). 正确捕获了异常,并且按预期方式将错误消息写入控制台,但是显然未调用我的Socket类的析构函数(它也应该向std :: cerr输出一条消息,但是该消息仅在连接有效且如果套接字超出堆栈,则稍后会销毁它,例如,在尝试利用套接字的函数末尾)。 The destructor should close the encapsulated socket, but on exception thrown the socket remains open (you can see it with lsof as socket of unknown type), so no code in the destructor seems to be executed at all). 析构函数应该关闭封装的套接字,但是在异常抛出时,套接字保持打开状态(您可以将lsof作为未知类型的套接字查看它),因此,析构函数中似乎根本没有代码执行。 As I couldn't reproduce this problem with a simple testcase, my guess is that it somehow has to do with the quite complex structure of my project: I have a core application containing the code for the Socket class and providing a Singleton class which offers methods that implement the protocol used for communication and return the results of a request, each call to one of these methods generates its own instance of a Socket and provides it with the necessary information about host and port to use. 由于我无法通过简单的测试用例来重现此问题,因此我猜想这与我项目的相当复杂的结构有关:我有一个核心应用程序,其中包含Socket类的代码,并提供一个Singleton类,该类提供这些方法实现了用于通信的协议并返回请求的结果,对这些方法之一的每次调用都会生成其自己的Socket实例,并向其提供有关要使用的主机和端口的必要信息。 To simplify socket generation and managment, a std::auto_ptr is used, which should delete the Socket if method has finished and stack is cleaned up, which works properly according to console output, but it should work the same way on an exception thrown, at least that is what was my opinion until now. 为了简化套接字的生成和管理,使用了std :: auto_ptr,如果方法已完成并且堆栈已清理,则应该删除Socket(根据控制台输出正确运行),但对于抛出的异常,其工作方式应相同,至少那是我到目前为止的看法。 The core is able to load plugins in shared object format by dlopen and gets a pointer to the plugin's class instance via an extern C declared function in the shared object. 内核能够通过dlopen加载共享对象格式的插件,并通过共享对象中通过extern C声明的函数获取指向插件类实例的指针。 This instance now uses the Singleton provided by the core to communicate with the server and show retrieved data. 现在,该实例使用核心提供的Singleton与服务器通信并显示检索到的数据。

My question is: are there limitations to stack unwinding when using shared objects, or where should I look for the thing I missed out to make this work properly? 我的问题是:在使用共享对象时,展开堆栈是否有限制,或者我应该在哪里寻找错过的东西以使其正常工作?

如果构造函数引发了异常,则不会调用析构函数。

Ok, forget that one. 好吧,忘了那个。 Another look in the code showed that there was the possibility that an exception could have been thrown already in constructor so that the destructor would not have been called, as it's described in C++ standard. 代码中的另一处外观显示,很可能已经在构造函数中引发了异常,因此就不会调用析构函数,如C ++标准中所述。 Not throwing in the constructor solved the problem. 不抛出构造函数即可解决问题。 That's what programming in Java is doing to your C++ skills ^^ Excuse the noise, please. 这就是Java编程对您的C ++技能所做的事情。^^请原谅。

If you are programming on linux, you might be triggering a problem where the exception thrown from a shared library is not caught properly (problem with exception type determining). 如果在Linux上进行编程,则可能会引发一个问题,即无法正确捕获从共享库引发的异常(确定异常类型的问题)。 This problem is explained here and here , and I am sure you could google up more pages explaining the same problem. 这个问题在这里这里都得到了解释,我相信您可以在Google上搜索更多页面来解释这个问题。

If that is a problem, I am still looking for a solution :( 如果那是一个问题,我仍在寻找解决方案:(

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM