我正在用 Rust 编写一个跨平台(Linux/iOS/Android)库。万一我的库发生恐慌,我希望应用程序继续正常工作而不是崩溃。为了做到这一点,我正在使用catch_unwind; 其结果包含恐慌信息,并且不包含有关问题根源的足够信息,这里有一段代码解释了我正在做的事情:
fn calculate(json: &str) -> String {
unimplemented!()
}
#[no_mangle]
pub fn rust_calculation(json: &str) -> String {
let r = std::panic::catch_unwind(||{
// rust calculation
let calc: String = calculate(json).into();
calc
});
let r_str = match r {
Ok(v) => v,
Err(e) => {
let panic_information = match e.downcast::<String>() {
Ok(v) => *v,
_ => "Unknown Source of Error".to_owned()
};
panic_information
}
};
return r_str;
}
fn main() {
println!("{}", rust_calculation("test"));
}
Run Code Online (Sandbox Code Playgroud)
如果发生错误,返回的消息是不够的,有时,它只包含消息
错误来源未知
我想将回溯发送到调用源,以便它可以记录它,然后我们可以调试 …
注意:我使用的是我在使用libxml-ruby gem时遇到的段错误来说明问题,但我已经修复了我的问题.这个问题的真正意义在于从gdb和核心文件中查看Ruby回溯(即解释器在Ruby代码无法处理异常时打印的内容),解释器本身遇到分段错误.
在生成XML文档的过程中,我遇到了一个奇怪的段错误:
/railsroot/vendor/isolated/ruby-1.8/gems/libxml-ruby-1.1.2/lib/libxml/node.rb:123: [BUG] Segmentation fault
ruby 1.8.7 (2011-02-18 patchlevel 334) [x86_64-linux], MBARI 0x6770, Ruby Enterprise Edition 2011.03
Aborted
Run Code Online (Sandbox Code Playgroud)
更新1:这也是在vanilla Ruby(MRI)下的段错误.
我已经打开了corefiles并查看了gdb中的backtrace(参见问题的结尾).我可以看到解释器崩溃的地方,谷歌搜索导致了许多有希望的结果.除了解释器回溯之外,我想看到的是Ruby代码本身的回溯(即从解释器的角度来看的回溯).
我希望在gdb中加载核心将允许我调用一些解释器函数来打印出解释代码的堆栈.
有任何想法吗?
对于好奇的人来说,这是核心和回溯:
: foo@bar; ulimit -c unlimited
: foo@bar; RAILS_ENV=production ./script/runner script/feeds/batchfeed.rb --config config/feeds/$feed.yml --timer /tmp/$feed.timer --gzip --output /tmp/$feed.xml.gz
/railsroot/vendor/isolated/ruby-1.8/gems/libxml-ruby-1.1.2/lib/libxml/node.rb:123: [BUG] Segmentation fault
ruby 1.8.7 (2011-02-18 patchlevel 334) [x86_64-linux], MBARI 0x6770, Ruby Enterprise Edition 2011.03
Aborted
: foo@bar; ls -l core
-rw------- 1 rails rails 145301504 2011-03-04 08:34 core
: …Run Code Online (Sandbox Code Playgroud) 我正在Linux上开发一个应用程序,我希望以特定频率回溯所有正在运行的线程.所以我的用户定义的信号处理程序SIGUSR1(对于所有线程)调用backtrace().
我在我的信号处理程序中发生崩溃(SIGSEGV),该处理程序源自backtrace()调用.我已经在大多数网站上指定了函数的正确参数. http://linux.die.net/man/3/backtrace.
在这种情况下,什么可能使backtrace()崩溃?
要添加更多详细信息:
是什么让我得出结论崩溃在内部回溯是下面的第14帧.onMySignal是信号处理程序SIGUSR1,它调用backtrace.
onMySignal的示例代码是(从backtrace的linux文档中复制)
pthread_mutex_lock( &sig_mutex );
int j, nptrs;
#define SIZE 100
void *buffer[100] = {NULL};//or void *buffer[100];
char **strings;
nptrs = backtrace(buffer, SIZE);
pthread_mutex_unlock( &sig_mutex );
Run Code Online (Sandbox Code Playgroud)
(gdb) where
#0 0x00000037bac0e9dd in raise () from
#1 0x00002aaabda936b2 in skgesigOSCrash () from
#2 0x00002aaabdd31705 in kpeDbgSignalHandler ()
#3 0x00002aaabda938c2 in skgesig_sigactionHandler ()
#4 <signal handler called>
#5 0x00000037ba030265 in raise () from
#6 0x00000037ba031d10 in abort () from
#7 0x00002b6cef82efd7 in os::abort(bool) () from
#8 0x00002b6cef98205d …Run Code Online (Sandbox Code Playgroud) 我在D中有以下示例代码:
import std.stdio;
int g(int i) {
auto l = [1, 2, 3, 4];
return l[i];
}
void f(int i) {
writeln(g(i));
}
void main(string[] args) {
f(1);
f(10);
f(2);
}
Run Code Online (Sandbox Code Playgroud)
我用DMD编译了这段代码(在OS X上使用v2.056).当我运行它时,它显然崩溃了:
core.exception.RangeError@test(5): Range violation
----------------
5 test 0x000b823a _d_array_bounds + 30
6 test 0x000aa44b D4test7__arrayZ + 27
7 test 0x000aa4ae int test.g(int) + 94
8 test 0x000aa4c7 void test.f(int) + 11
9 test 0x000aa422 _Dmain + 26
10 test 0x000b87b3 extern (C) int rt.dmain2.main(int, char**).void runMain() + 23 …Run Code Online (Sandbox Code Playgroud) 我正在使用backtrace打印应用程序的堆栈跟踪,我得到类似的东西
libQtCore.so.4(_ZN11QMetaObject8activateEP7QObjectPKS_iPPv+0x843) [0x7f889d20cf33]
libQtGui.so.4(_ZN7QAction9triggeredEb+0x32) [0x7f889d76c2f2]
libQtGui.so.4(_ZN7QAction8activateENS_11ActionEventE+0xb0) [0x7f889d76d670]
libQtGui.so.4(+0x6242f4) [0x7f889db862f4]
Run Code Online (Sandbox Code Playgroud)
有没有办法将"链接器名称"转换为"源名称"并从偏移量中获取代码行号?
我想要回溯,看起来像这样:
libQtCore.so.4 (QMetaObject::activate(QObject):1022)
libQtGui.so.4 (QAction::triggered()::47)
Run Code Online (Sandbox Code Playgroud)
UPD.
据我所知,由于编译器的细节,这种技术可能起作用或不起作用或工作不好.我想至少在gcc和visual c ++中"demangle"链接符号.
我使用backtrace()和backtrace_symbols()来输出SIGSEGV和其他信号的回溯,格式如下:
0: [0xb750818]
1: /opt/server/libQtScript.so.4(+0x6f42a) [0xb782c42a]
2: /opt/server/libQtScript.so.4(+0x7bffc) [0xb7838ffc]
3: /opt/server/libQtScript.so.4(+0x86946) [0xb7843946]
4: /opt/server/libQtScript.so.4(+0x7c4bc) [0xb78394bc]
5: /opt/server/libQtScript.so.4(+0x86946) [0xb7843946]
6: /opt/server/libQtScript.so.4(+0x9603e) [0xb785303e]
7: /opt/server/libQtScript.so.4(_ZN12QScriptValue4callERKS_RK5QListIS_E+0x2e7) [0xb7891647]
Run Code Online (Sandbox Code Playgroud)
在这种特殊情况下,帧#7对我来说很好,尽管帧1-6给了我一些"+ x"地址.
如何在"+ 0x6f42a"和GDB中的其他地址反汇编中得到确切的行?什么帧#0,没有描述模块,意味着什么?
我想在MIPS上做回溯.然后,我面临一个问题:如何获得当前的PC寄存器值,因为它不属于32个普通寄存器..感谢您的建议..
我想了解我的软件中特定线程的状态,它是从另一个线程执行的。具体来说,我想知道它是否卡住了I / O。我正在考虑通过获取backtrace来做到这一点(除非有人有其他想法?),因为我知道应该将其保留在哪个函数上..但我不知道如何获取该特定线程的backtrace,调用SEGFAULT处理程序...但是gdb可以做到(我怀疑他创建了SEGFAULTS ..)
有人可以帮忙吗?任何的想法?
[编辑]所有3个答案都涉及gdb,我知道我可以从gdb做到这一点,我想知道如何从软件中做到这一点(即使以某种方式链接到gdb库也可以解决,但如何?)
glibc的提供了非常方便backtrace()和backtrace_symbols()功能,它可以帮助获取当前函数的堆栈跟踪程序(见这里)。
Windows API是否提供任何类似的功能?
每次应用程序崩溃时,我都想显示一个带有类和方法名称的回溯.我设法在调试模式下使用此代码执行此操作(该printTrace函数只是在文件上打印字符串.):
void HandleException(NSException *exception)
{
[SILogManager printTrace:[NSString stringWithFormat:@"******************** CRASH *********************"]];
[SILogManager printTrace:[NSString stringWithFormat:@"-> Stack Trace: %@", [exception callStackSymbols]]];
}
Run Code Online (Sandbox Code Playgroud)
虽然这在应用程序发布时不起作用,因为它会产生类似这样的堆栈跟踪:
******************** CRASH *********************
-> Stack Trace: (
0 CoreFoundation 0x27b5f60f <redacted> + 150
1 libobjc.A.dylib 0x35613c77 objc_exception_throw + 38
2 CoreFoundation 0x27a733a7 <redacted> + 178
3 iSelz POS 0x000bf6c7 iSelz POS + 403143
4 iSelz POS 0x000bf099 iSelz POS + 401561
5 iSelz POS 0x000dda31 iSelz POS + 526897
6 CFNetwork 0x276b7eed <redacted> + 56
7 CFNetwork 0x276b7ea7 …Run Code Online (Sandbox Code Playgroud)