简体   繁体   English

gdb显示奇怪的堆栈跟踪

[英]gdb shows weird stack trace

I have a C++ daemon which segfaults after few days of work. 我有一个C ++守护程序,经过几天的工作后它会出现段错误。 I compiled it with debug options (I'm sure I did it well, because I tested it with premeditated crashes and gdb showed correct stack trace), but in "real" crash on production I see only following trace: 我使用调试选项对其进行了编译(我确信我做得很好,因为我已经过预先测试的崩溃进行了测试,并且gdb显示了正确的堆栈跟踪),但是在生产中出现的“真正”崩溃中,我仅看到以下跟踪:

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

What does it mean? 这是什么意思?

The following source code has potential issue, because it is the only new code since daemon become unstable: 以下源代码有潜在的问题,因为这是守护程序变得不稳定以来唯一的新代码:

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;
    }
}

Shouldn't the second if in your getByIp(...) method look like this? 应该不是第二,如果getByIp(...)方法这个样子的?

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

If you are indeed missing the curly braces, you might be dereferencing invalid pointers when you retrieve the lng string, because its retrieval is then not a part of the conditional statement. 如果确实缺少花括号,则在检索lng字符串时,您可能会取消引用无效的指针,因为那样,对它的检索就不再是条件语句的一部分。

It looks like a memory corruption affecting the stack: writing outside of the allocated memory. 它看起来像是影响堆栈的内存损坏:在分配的内存之外进行写操作。

You can write a little program to exercise your Bar class the same way your daemon does, possibly in a loop. 您可以编写一个小程序来以与守护程序相同的方式练习Bar类,可能是在循环中。 You can also run this program with MALLOC_CHECK_ , electric fence , Valgrind or any other memory checking tool. 您也可以使用MALLOC_CHECK_电围栏 ,Valgrind或任何其他内存检查工具运行该程序。

It could be curl, TiXmlDocument, or the code calling your class. 它可以是curl,TiXmlDocument或调用您的类的代码。

I expect you have a few issues with pointers. 我希望您在使用指针时遇到一些问题。 As StackTrace #0 shows a function within libc.so.6 that does not have a name. 正如StackTrace#0所示,libc.so.6中的函数没有名称。 And #1 has a NULL -1 pointer. #1具有NULL -1指针。 We need a lot more to help you fix your bug. 我们需要更多帮助您修复错误的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM