gdb 显示奇怪的堆栈跟踪
Posted
技术标签:
【中文标题】gdb 显示奇怪的堆栈跟踪【英文标题】:gdb shows weird stack trace 【发布时间】:2014-02-17 07:24:53 【问题描述】:我有一个 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;
【问题讨论】:
【参考方案1】:看起来像影响堆栈的内存损坏:在分配的内存之外写入。
您可以编写一个小程序来执行您的 Bar 类,就像您的守护程序一样,可能在一个循环中。您也可以使用MALLOC_CHECK_、electric fence、Valgrind 或任何其他内存检查工具运行此程序。
可能是 curl、TiXmlDocument 或调用您的类的代码。
【讨论】:
【参考方案2】:您的 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 字符串时取消引用无效指针,因为它的检索不是条件语句的一部分。
【讨论】:
我的错,对不起,但这部分代码看起来有点不同,这不是原因,我已经更新了代码。代码是专有的,我无法按原样显示,这就是我没有复制粘贴它的原因。但是其余的代码是一样的,只是变量/类名不同。 我感觉这更像是一个复制粘贴错误,但我指出了这一点,所以我们不会遗漏任何明显的东西。祝你有美好的一天:-)。 否则这段代码显然不会被编译;)【参考方案3】:我希望您对指针有一些问题。由于 StackTrace #0 显示了 libc.so.6 中没有名称的函数。并且 #1 有一个 NULL -1 指针。我们需要更多帮助您修复错误。
【讨论】:
我添加了可能有错误的代码。也许 cURL 有内部错误/内存泄漏,我有时必须重新初始化它?以上是关于gdb 显示奇怪的堆栈跟踪的主要内容,如果未能解决你的问题,请参考以下文章