gdb显示了奇怪的堆栈跟踪

时间:2014-02-17 07:24:53

标签: c++ curl gdb

我有一个C ++守护程序,经过几天的工作后会出现段错误。我用调试选项编译它(我确信我做得很好,因为我用预谋的崩溃测试了它并且gdb显示了正确的堆栈跟踪),但是在生产中的“真实”崩溃中我只看到跟踪:

(gdb) where
#0  0x00007ffff674d5a7 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1  0xffffffffffffffff in ?? ()
#2  0x0000000000000000 in ?? ()

这是什么意思?

以下源代码存在潜在问题,因为它是自守护程序变得不稳定以来唯一的新代码:

namespace Foo {
    Bar* Bar::instance = NULL;

    Bar* Bar::getInstance() {
        if (!instance)
            instance = new Bar();

        return instance;
    }

    Bar::Bar() {
        curl = curl_easy_init();

        if(CURLE_OK != curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &data_write)
        || CURLE_OK != curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L)
        || CURLE_OK != curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L)
        || CURLE_OK != curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, Bar::timeout)) {
            throw std::runtime_error(std::string("Can't initialize curl."));
        }
    }

    Bar::~Bar() {
        curl_easy_cleanup(curl);
    }

    std::string Bar::getByIp(const std::string &id) {
        Bar *self = getInstance();
        std::string url = "example.com";
        url.append(id); 

        std::ostringstream oss;

        if (CURLE_OK == self->curl_read(url, oss)) {
            std::string output(oss.str());

            if (output.empty())
                return NULL_OBJECT;

            TiXmlDocument xml;
            xml.Parse(output.c_str());

           if (
                xml.Error()
                || !xml.FirstChild("a")
                || !xml.FirstChild("a")->FirstChild("b")
                || !xml.FirstChild("a")->FirstChild("b")->FirstChildElement("lat")
                || !xml.FirstChild("a")->FirstChild("b")->FirstChildElement("lng")
            )
                return NULL_OBJECT;

            std::string lat = xml.FirstChild("a")->FirstChild("b")->FirstChildElement("lat")->GetText();
            std::string lng = xml.FirstChild("a")->FirstChild("b")->FirstChildElement("lng")->GetText();

            return Region::getByCoordinates(lng, lat);
        }

        return NULL_OBJECT;
    }

    size_t Bar::data_write(void* buf, size_t size, size_t nmemb, void* userp)
    {
        if(userp)
        {
            std::ostream& os = *static_cast<std::ostream*>(userp);
            std::streamsize len = size * nmemb;
            if(os.write(static_cast<char*>(buf), len))
                return len;
        }

        return 0;
    }

    CURLcode Bar::curl_read(const std::string& url, std::ostringstream& os)
    {
        CURLcode code(CURLE_FAILED_INIT);

        if(curl)
        {
            if(
                CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FILE, &os))
                && CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_URL, url.c_str()))
            ) {
                code = curl_easy_perform(curl);
            }
        }

        return code;
    }
}

3 个答案:

答案 0 :(得分:1)

getByIp(...)方法中的第二个 if 是否应该如下所示?

if (xml.Error()
    || !xml.FirstChild("a")
    || !xml.FirstChild("a")->FirstChild("b")
    || !xml.FirstChild("a")->FirstChild("b")->FirstChildElement("lat")
    || !xml.FirstChild("a")->FirstChild("b")->FirstChildElement("lng")) // <- added missing parenthesis
{ // <- added
    std::string lat = xml.FirstChild("a")->FirstChild("b")->FirstChildElement("lat")->GetText();
    std::string lng = xml.FirstChild("a")->FirstChild("b")->FirstChildElement("lng")->GetText();
    return Region::getByCoordinates(lng, lat);
} // <- added

如果确实缺少大括号,则在检索 lng 字符串时可能会取消引用无效指针,因为它的检索不是条件语句的一部分。

答案 1 :(得分:1)

它看起来像是影响堆栈的内存损坏:在已分配的内存之外写入。

你可以编写一个小程序来练习你的Bar类,就像守护进程一样,可能是循环。您还可以使用MALLOC_CHECK_electric fence,Valgrind或任何其他内存检查工具运行此程序。

可能是curl,TiXmlDocument或调用你的类的代码。

答案 2 :(得分:0)

我希望你有一些关于指针的问题。由于StackTrace#0在libc.so.6中显示了一个没有名称的函数。 #1有一个NULL -1指针。我们还需要更多帮助您修复错误。