Linux分段错误与std :: string :: iterator

时间:2013-12-24 18:59:46

标签: c++ string sockets iterator segmentation-fault

我在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() ()

这是有问题的代码似乎触发了段错误:

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编译

谢谢!

内特

2 个答案:

答案 0 :(得分:2)

使用静态变量(Buffer)不是线程安全的。可能会导致崩溃。

您应该添加Line不是NULL的支票。

顺便说一句,行Buffer = std::string("");可以是Buffer.clear();

答案 1 :(得分:1)

除静态变量问题外,您确定收到的数据是否包含嵌入的NULL字符吗?

如果生成的Buffer包含嵌入的NULL字节,则此行不会使用+ =运算符执行正确的连接:

Buffer += Bucket;

+ =重载假定Bucket是一个c风格的字符串,因此遇到的第一个NULL字节将在连接发生时用作终结符。

看一下代码,似乎情况是如果Bucket确实包含嵌入的NULL chracters,执行上面的连接可能会导致你的“iter”迭代器指向传递Buffer的end()(in while()循环后的那些行。

相反,你可以这样做:

Buffer.append(Bucket, BytesRecv)

这可以保证Bucket正在寻址的所有字符将连接到现有字符串上。

但在进行任何更改之前,请确保您确切知道问题所在,特别是因为您声明错误不会经常发生。在不首先知道错误的真正原因的情况下更改代码可能只是掩盖错误,从而使得更难以诊断真正的问题。