1

希望你今天过得愉快。

我正在研究一个类来包装 Berkley C Networking API,到目前为止,我只得到了一个 TCP 服务器/客户端。

具有讽刺意味的是,我遇到的问题不在于网络,而在于堆栈和堆。也许我根本不完全理解它,但是当我使用类似的东西时: ClientSocket *mysock = new ClientSocket(); 并且只需使用 -> 运算符调用函数,它就可以正常工作 - 如果发生错误,我的 SocketException 类会被捕获没有问题。

但是,当我使用: ClientSocket mysock; 并且在使用 . 运算符,它显示: terminate called after throwing an instance of 'SocketException' Aborted 只是让我回到终端提示符。

忘了补充,我将调用包装在 try/catch 块中。

我知道第一个示例是使用“new”关键字返回指向堆上新 ClientSocket 实例的指针,第二个示例用于堆栈,但我不知道问题所在。

我在想我错过了一些关于指针/引用/堆栈/堆的东西,但我不知道发生了什么。代码通常运行得很好,但是如果抛出任何异常...... >:(

编辑:在链接页面上,Client.cxx 和 Server.cxx 是示例文件!感谢您指出这一点,埃里克。对此的帮助将不胜感激。该项目的来源位于:
所有文件的链接:http: //furryhead.co.cc/problem.html
(我不能粘贴超过 2 个链接,而且我有 4 个文件,所以必须这样做,直到有人可以将链接合并到我的帖子中)注意:Socket.cxx 相当大,因为它包含 ServerSocket、ClientSocket 和 SocketException 定义。

编译上述所有文件的命令是:
g++ -c Socket.cxx -o Socket.o
g++ -c Server.cxx -o Server.o
g++ -c Client.cxx -o Client.o
g++ Server.o Socket.o -o 服务器
g++ Client.o Socket.o -o 客户端

谢谢!

很少更新,根据 Jon 的建议,我查找了套接字函数的文档,现在它有更好的错误报告——我检查了 'errno' 变量并基于它抛出异常。(那个,而且我没有将它设置为非阻塞......;)) - 只是想更新并表示感谢!:D

4

2 回答 2

7

对我来说,这听起来像是出于正当原因引发的异常,并且在展开堆栈期间某些对象的(可能是ClientSocket's?)析构函数抛出。由于运行时无法以任何有意义的方式解决这种情况(同时“抛出”两个异常),因此terminate调用该函数并关闭程序。

未回答的问题是,如果某个析构函数所属的对象在堆栈上分配,为什么会抛出该问题。但要回答这个问题需要更多的数据。也许你可以更深入地挖掘并检验我的假设?

顺便说一句,如果情况确实如此,并且由于任何析构函数都不应该抛出任何 东西 ,我们可以得出结论,违规类存在致命缺陷。

更新:看来我是在赚钱。

你的类Socket的析构函数调用close,并且close可以抛出。这是一个严重的编程错误。您应该将调用包装close在析构函数中

try {
    close();
}
catch(...)
{ /* this space intentionally left blank */ }

崩溃就会消失。

第二次更新(不再崩溃)

如果recv返回 -1,这意味着套接字处于非阻塞模式并且当前没有可接收的数据。这不是一个错误,而是一个特性。你不应该在那里抛出异常。您该做什么完全取决于您是要在阻塞模式还是非阻塞模式下使用套接字。

于 2011-03-13T00:03:47.303 回答
0

Jon 已经解决了终止问题,但是原始代码中还有另一个问题。

动态分配的对象似乎起作用的原因是,当其他地方出现异常时,它会被泄漏并且永远不会调用析构函数。虽然这避免了双重异常问题,但它稍后会导致另一个集合......

于 2011-03-13T08:00:46.513 回答