问题
前些日子在查找网络 Socket 问题时遇到了一个较为特殊的错误打印:errno = 2,该错误码指向的意思是 No such file or directory,那么问题来了…
先看代码片段
#define NET_Debug(fmt, arg...) fprintf(stdout, " %s-%d "fmt" ", __FILE__, __LINE__, ##arg)
...
iHaveRecv = ::recv(m_iSockFd, pMsgBuf, iBufLen, 0);
if (0 > iHaveRecv )
{
NET_Debug("errno = %d, %s\n", errno, strerror(errno));
}
...
上面的代码想要捕获 recv 函数错误的原因,通过 NET_Debug 函数打印错误码 errno,然后进行错误分析,解决问题。但是,该 errno 打印出来的结果与实际却不相符,从而误导了方向。
为何会如此呢?
errno 是 Linux 系统里的一个全局变量,保存最近一次的出错信息代号。因为是全局的,所以他是可能会被其他函数修改的。而上述代码中,fprintf 函数就会修改 errno 的值,从而使得问题的方向被带偏。
解决
正确的写法有两种:
一、出错后立马判断 errno 的值,并进行相应的处理,同时这些处理不会再使用 errno 的值。
二、出错后立马保存 errno 的值(个人喜欢并推荐),使用保存值进行相应的判断与处理。
以下为方法二的一种写法
#define NET_Debug(fmt, arg...) fprintf(stdout, " %s-%d "fmt" ", __FILE__, __LINE__, ##arg)
...
iHaveRecv = ::recv(m_iSockFd, pMsgBuf, iBufLen, 0);
int iTmpErrno = errno;
if (0 > iHaveRecv )
{
NET_Debug("errno = %d, %s\n", iTmpErrno , strerror(iTmpErrno ));
}
...
这个问题对于一般 Linux 新手工程师来说可能都不会意识到吧…
假装陷入沉思中…
齐烟九点 意尽天明