2011-10-11 131 views
4

我使用Boost 1.45 ASIO来处理在Windows和Mac上运行的应用程序中的某些套接字连接。在Windows上,下面的代码不会导致任何错误,并且我的套接字是干净地关闭的。不过,在Mac上,关机和(如果我注释掉)关闭功能给我“错误的文件描述符”错误。直到我称之为代码,套接字工作正常。但只要我叫停或关闭,我得到错误。任何想法可能会发生什么?错误的文件描述符关闭Boost套接字

if(socket.is_open()) 
{ 
    socket.shutdown(socket.both); 
    socket.close(); 
} 
+0

这将有助于,如果你能澄清这段代码的意图。通常,'〜socket()'dtor关闭底层本地描述符类型。你明确关闭它有什么原因吗? –

+0

我以为你确实需要关闭套接字 - 这个错误当然不会导致任何问题(除了错误本身),所以如果我不需要明确地关闭套接字,那么我会很乐意接受那个出来,继续我的生活。所以澄清,我是否应该不需要关闭或关闭? –

+0

我已经添加了答案 –

回答

1
if(socket.is_open()) 
{ 
    socket.shutdown(socket.both); 
    socket.close(); 
} 

除非你有一个很好的理由这样做,我建议让socket::~socket()析构函数关闭底层本地文件描述符。如果您担心泄漏描述符,请使用valgrind这样的工具来分析您的程序。

+0

这不就是忽略错误吗? – Nemo

+0

这并不是真的忽略了错误。 asio库将描述符的原生基础类型抽象出来,并且不需要显式关闭以防止资源泄漏。如果程序双关闭描述符中存在错误,则可能在其他位置。 –

+0

该错误可能在其他地方,但错误发生在这里......而且我相当确定提升人员不会抛出任何异常从他们的析构函数。所以你的建议是忽略问题而不是解决问题。 (无法检测close()上的错误是为什么依赖析构函数通常是不好的风格,IMO。在这种情况下,它绝对忽略了一个真正的问题,无论这个问题是什么)。 – Nemo

0

我有同样的问题:在Windows上一切正常,并在Linux上,根据套接字状态IIRC抛出异常。

Sam的答案的替代方法是使用虚拟error_code来默默地忽略异常,如果它发生。请参阅asio文档中的closeshutdown重载。

7
上的“错误文件描述符”通常表示描述符已经关闭。这通常是因为程序中某个完全不相关的部分出现了双关闭错误。

这样的错误可以传染。如果程序关闭了两次相同的描述符,并在此期间重新分配,则第二个将关闭某个不相关对象的描述符。然后当这个对象关闭它的描述符时,它实际上可以关闭另一个对象的描述符......等等,直到最后一个在行中出现“坏文件描述符”错误。

这是(a)描述符是全局状态和(b)Unix要求任何调用open/socket/etc的副作用。分配编号最小的未使用描述符。

我知道调试这个的唯一方法是使用像strace(在Linux上)或dtrace(在Mac上)的工具来监视所有文件描述符的创建和销毁。 (嗯,也许不是唯一的方法,我曾经写了一个令人费解的LD_PRELOAD黑客截取每个呼叫openclose找出哪个线程是双关闭他们的描述符,因为第二个关闭是nuking描述符被另一个线程使用。 ..)

祝你好运。