我正在尝试调试我用gdb编写的服务器,因为它在非常特殊和罕见的条件下进行了段错误.
有什么方法可以让gdb在后台运行(通过安静或批处理模式?),跟随子项(因为我的服务器是守护进程并从主PID中分离)并自动转储核心和回溯(到指定的文件) )一旦程序崩溃了?
我对一个信号处理程序感兴趣,它可以识别导致问题的指令的地址.
我知道siginfo_t并且__builtin_return_address似乎都没有工作:
#include <iostream>
#include <signal.h>
void handler (int, siginfo_t *, void *);
int main ()
{
begin:
std :: cerr << &&begin << " ~ " << &&before << " ~ " << &&after << "\n";
struct sigaction s;
s .sa_flags = SA_SIGINFO;
sigemptyset (& s .sa_mask);
s .sa_sigaction = handler;
sigaction (SIGSEGV, &s, NULL);
int * i = NULL;
before:
*i = 0;
after:
std :: cout << "End.\n";
}
void handler (int, siginfo_t …Run Code Online (Sandbox Code Playgroud) 有没有办法在C++ 11(使用最新的GCC)中获取调用当前执行的方法(调用者)的方法的名称,或文件和行号?
我想在错误消息中使用此信息,例如,以下代码失败:
void SomewhereInMyProgram()
{
DoSomething(nullptr);
}
void DoSomething(const char* str)
{
Contract::Requires(str != nullptr);
// ...
}
Run Code Online (Sandbox Code Playgroud)
目前我有代码报告错误发生在DoSomething.虽然这在技术上是正确的,但我希望它报告错误发生在SomewhereInMyProgram任何可能的地方.这会让我的生活变得更轻松!
该解决方案可以使用任何C++ 11功能,宏或GCC特定的东西,但不是我必须在每个呼叫站点添加的东西.
我认为堆栈跟踪不会帮助我,因为我不能使用异常处理.实际上,我非常有限:它是一个独立的环境,标准的C++标头不可用.我希望得到某种宏观解决方案.
class Contract
{
public:
static void RequiresImpl(bool condition, const char* expression,
const char* file, int line);
#define Requires(condition) RequiresImpl(condition, #condition , \
__FILE__, __LINE__ )
};
Run Code Online (Sandbox Code Playgroud) 我想在main中对当前堆栈进行校验和,以检查它是否在两点之间被改变.
例如:
int main(void) {
...
stack_checksum();
... process ...
if(stack_checksum() != ...)
altered.
}
Run Code Online (Sandbox Code Playgroud)
如何获取基本堆栈地址和堆栈顶部的当前地址?
编辑: 随着@MiroslavBajtoš帮助,步骤方法:
我正在尝试使用增强路径执行几乎任何操作,从而获得一致的段错误.
(编辑:似乎所有segfaulting函数都与之相关current_path())
Sample program:
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <iostream>
using namespace std;
using namespace boost::filesystem;
using namespace boost::system;
int main(int argc, const char * argv[])
{
error_code err;
auto p = path("hello/../world");
cout << p.string() << endl;
path c = canonical(p, err);
cout << c.string() << endl;
}
Run Code Online (Sandbox Code Playgroud)
以上只是一个例子,以下也是段错:
auto p = current_path(err);
和:
auto p = initial_path(err);
编译:
g++-4.9 -lboost_filesystem -lboost_system -std=c++11 main.cpp -o ./path-test
输出:
hello/../world
Segmentation fault: 11
Run Code Online (Sandbox Code Playgroud)
通过Homebrew安装GCC和Boost . …
我刚读完
现在已经很老了(5年)。一些答案提出了解决方案,允许您为每个堆栈帧获取函数的名称和偏移量(我猜是在堆栈内)。但是我(可能还有其他人)真正需要的是进行调用的源文件名和行号(假设代码是用调试信息编译的)。链接到执行此操作的 glibc 的一部分的答案之一(libSegfault;请参阅此目录中的文件- segfault.c, backtracesyms.c, backtracesymsfd.c) - 所以它是可能的。
我的问题是:
笔记:
-g; 当然,在适当的库中,我们会检查调试信息是否可用。有时我的c ++程序在调试模式下崩溃,我得到的是一个消息框,说明某些内部内存管理例程中的断言失败(访问未分配的内存等).但我不知道从哪里调用,因为我没有得到任何堆栈跟踪.如何获取堆栈跟踪或至少查看我的代码中的失败位置(而不是库/内置例程)?
另外,该程序在运行Linux的arm设备上运行,我可以打印出堆栈信息并在我指定的sig-seg处理程序中注册值.问题是我无法在源文件中添加-g选项,因为由于性能降级,错误可能无法重现.
我一直在我的程序中遇到分段错误,但没有生成核心转储文件。ulimit 显示了一个无限制的值,为了确定 ulimit -c 没有限制,它似乎没问题。有任何想法吗?
我正在尝试编译显示代码的示例堆栈跟踪.当我用以下代码编译test.c文件时:
gcc -g -rdynamic ./test.c -o test
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
./test.c: In function ‘handler’:
./test.c:16: error: ‘STDERR_FILENO’ undeclared (first use in this function)
./test.c:16: error: (Each undeclared identifier is reported only once
./test.c:16: error: for each function it appears in.)
Run Code Online (Sandbox Code Playgroud)
我的包含与原始邮政编码相同:
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
Run Code Online (Sandbox Code Playgroud)
我的机器是ubuntu 13.04.我错过了一些图书馆还是没有包含一些内容?