GDB 显示奇怪的堆栈跟踪
gdb shows weird stack trace
我有一个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;
}
}
它看起来像是影响堆栈的内存损坏:在分配的内存之外写入。
你可以编写一个小程序来练习你的 Bar 类,就像你的守护程序一样,可能是在一个循环中。您还可以使用MALLOC_CHECK_,电围栏,Valgrind或任何其他内存检查工具运行此程序。
它可以是curl,TiXmlDocument或调用类的代码。
在你的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 字符串时可能会取消引用无效指针,因为它的检索不是条件语句的一部分。
我希望您对指针有一些问题。正如 StackTrace #0 所示,libc.so.6 中有一个没有名称的函数。#1 有一个空 -1 指针。我们需要更多来帮助您修复错误。
相关文章:
- 用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
- 提升堆栈跟踪不显示函数名称和行号
- cygwin_exception::open_stackdumpfile:将堆栈跟踪转储到 class4.exe.sta
- 如何按指针查看堆栈跟踪
- WinDbg 不显示某些小型转储文件的完整堆栈跟踪
- 发布代码的 gdb 堆栈跟踪可读性如何影响 x64?
- 提升::堆栈跟踪::safe_dump_to输出大小
- Qt 5.9中的QML崩溃-帮助读取堆栈跟踪
- 如何获取崩溃的DLL的堆栈跟踪?
- 当外部源代码中发生异常时,无法正确使用自创建的小型转储文件的堆栈跟踪
- 在 Linux 平台上以 C/C++ 打印进程的所有线程堆栈跟踪
- Boost 堆栈跟踪异步信号安全吗?
- 使用 gdb 时无法获取堆栈跟踪
- VC++ 堆栈跟踪不会解析生产环境中的函数名称
- 从堆栈跟踪中查找共享库中的源代码行
- 捕获异常后的堆栈跟踪
- 是否有一种便携式/标准的方法可以在堆栈跟踪中获取文件名和亚麻布
- 为什么谷歌测试不打印堆栈跟踪或文件名
- 在明夫中打印堆栈跟踪
- GDB 显示奇怪的堆栈跟踪