gpt4 book ai didi

c++ - 如何避免坏的 FD_SET 缓冲区溢出崩溃?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:23:17 28 4
gpt4 key购买 nike

最近被FD_SET缓冲区溢出咬了两次。第一次是我们有太多套接字 (1024+) 添加到 FD_SET 中。这是一个测试用例,我们已将其禁用,并添加 assert 来检测此用例。

今天,当我们运行一个测试用例超过 1000 次时,我们遇到了另一个相关问题。每次,测试用例都会以某种方式触发分配一个套接字,然后在测试用例完成之前释放它。当我们运行 1000+ 次时,此测试用例将命中 FD_SET 缓冲区溢出。

我们找到了根本原因:

  1. 每pass一次,分配的socket id会增加(+1),很长一段时间内不会重复使用socket id。 操作系统MAC,我认为这是一个合理的设计,可以避免使用已经释放的套接字而不会发生错误。
  2. FD_SET 只是设置fd_set 位数组,以socket id 为索引,如果socket id 很大,会溢出。我认为 fd_set 是一个糟糕的设计。

我们认为 1000+ 是一个合理的数字。而且我们不认为定义 MACRO 来设置 'fd_set' 巨大是不合理的,并且在等待时浪费内存和 CPU。

我们不知道如何解决它,所以有什么建议吗?

------------编辑1----------------

原来在其他地方有套接字泄漏,这违反了析构函数应该释放所有资源。这使得套接字 ID 增加。所以项目#1 是不正确的。操作系统将重用套接字 ID。但无论如何,讨论是有帮助的,FD_SET 是糟糕的设计,我们应该使用 poll()

最佳答案

此答案总结了 OP 找到的解决方案,以及 rob mayoff 和 Joseph Quinsey 的评论。

如果一个程序没有重用一个文件描述符(你称之为“socket id”),它就不会关闭这个文件描述符。尝试在您的测试程序运行一段时间后运行 lsof。您可能会在输出中发现许多打开的套接字。 (但是 OP 说 lsof -g PID 似乎不适用于调试过程)。

或者,尝试 netstat -a -p --inet | grep process-name-or-pid.

在某些系统上,有时对套接字的简单 close(fd) 是不够的。如果您的套接字文件描述符不断增加,那么答案 close() is not closing socket properly可能有帮助。

为了避免 FD_SETSIZE 的问题,一些作者,例如 Increasing limit of FD_SETSIZE and select ,建议使用 poll 而不是 select

最后,OP 解决了这个问题:

It turned out there was socket leak in another place, which violate destructor should release all resource. And this made the socket id increase. Fixed, the operating system will reuse the socket id.

But anyway, the discussion is helpful, and the FD_SET is bad design, and we should using poll().

请注意,类 Unix 系统总是(或通常)使用最小的可用文件描述符。例如,open(2) 的手册页指出;

The file descriptor returned by a successful call will be the lowest-numbered file descriptor not currently open for the process.

关于c++ - 如何避免坏的 FD_SET 缓冲区溢出崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22827510/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com