我在一台CentOS 6.4 64位机器上的libc.so.6中不断出现异常的分段错误。这是gdb最常报告的回溯:
0x00007ffff60d9b3f in memcpy () from /lib64/libc.so.6
(gdb) backtrace
#0 0x00007ffff60d9b3f in memcpy () from /lib64/libc.so.6
#1 0x00000000004b6a6b in std::string::_S_construct<__gnu_cxx::__normal_iterator<char*, std::string> > ()
#2 0x00000000004b719b in NewsMAIL::SMTPClient::receiveLine(std::basic_string<char, std::char_traits<char>, std::allocator<char> >*) ()
#3 0x00000000004b776f in NewsMAIL::SMTPClient::handleResponse() ()
这是有问题的代码,似乎触发了segfault:
bool SMTPClient::receiveLine(std::string* Line)
{
static std::string Buffer;
std::string::iterator iter;
while((iter = std::find(Buffer.begin(), Buffer.end(), 'n')) == Buffer.end()) {
char Bucket[MAX_BUCKET_SIZE + 1] = {};
int BytesRecv = read(m_Socket, Bucket, MAX_BUCKET_SIZE);
//Did we get a socket error?
if(BytesRecv == -1) {
//This is generally considered a bad thing..
*Line = Buffer;
Buffer = std::string("");
return false;
}
Bucket[BytesRecv] = 0;
Buffer += Bucket;
}
*Line = std::string(Buffer.begin(), iter);
Buffer = std::string(iter + 1, Buffer.end());
return true;
}
有时它能100%工作,没有任何故障,所以不幸的是,并非每次都是这样。上面的代码是此代码的一个稍微修改的版本:https://stackoverflow.com/a/1584620/3133245
有人想过为什么会发生这种事吗?我正在使用g++4.7.2 进行编译
谢谢!
内特
使用静态变量(Buffer)不是线程安全的。可能导致崩溃。
您应该添加一个检查Line
不是NULL
。
BTW,线路Buffer = std::string("");
可以是Buffer.clear();
除了静态变量问题外,您确定接收到的数据不包含嵌入的NULL字符吗?
如果生成的Buffer包含嵌入的NULL字节,则此行将不会使用+=运算符进行正确的串联:
Buffer += Bucket;
+=重载假设Bucket是一个c风格的字符串,因此当发生串联时,遇到的第一个NULL字节将用作终止符。
看一眼代码,似乎是这样的情况:如果Bucket确实包含嵌入的NULL chracter,那么进行上述连接可能会导致"iter"迭代器指向传递了Buffer的end()(在while()循环之后的那些行中)。
相反,你可以这样做:
Buffer.append(Bucket, BytesRecv)
这保证了Bucket正在寻址的所有字符都将连接到现有字符串上。
但在做出任何更改之前,请确保您确切地知道问题所在,尤其是因为您声明错误不会经常发生。在不知道错误真正原因的情况下更改代码可能会掩盖错误,从而使诊断真正问题变得更加困难。