我正在使用C#.net进行应用程序开发.
要记录和调试异常,我使用stacktrace.
我在另一台机器上执行了我的应用程序,但是当发生错误时它指的是我的开发机器的路径.
Ex: D:\Projects\xyz.CS line no :12 _Error_message_here.
Run Code Online (Sandbox Code Playgroud)
为什么即使我在另一台机器上运行应用程序,它也会跟踪我的开发机器路径上的路径?
我正在写一个我想要移植的库.因此,它不应该依赖于glibc或Microsoft扩展或标准中没有的任何其他内容.我有一个很好的从std :: exception派生的类层次结构,我用它来处理逻辑和输入中的错误.知道在特定文件和行号处抛出特定类型的异常是有用的,但是知道执行的执行方式可能会更有价值,所以我一直在寻找获取堆栈跟踪的方法.
我知道,使用execinfo.h功能(见的是glibc建造时这个数据是可用的质疑76822),并通过微软的C++实现的StackWalk接口(见问题126450),但我非常希望避免任何的不便携.
我正在考虑以这种形式自己实现这个功能:
class myException : public std::exception
{
public:
...
void AddCall( std::string s )
{ m_vCallStack.push_back( s ); }
std::string ToStr() const
{
std::string l_sRet = "";
...
l_sRet += "Call stack:\n";
for( int i = 0; i < m_vCallStack.size(); i++ )
l_sRet += " " + m_vCallStack[i] + "\n";
...
return l_sRet;
}
private:
...
std::vector< std::string > m_vCallStack;
};
ret_type some_function( param_1, param_2, param_3 )
{
try
{
...
} …Run Code Online (Sandbox Code Playgroud) 我正在开发一个非常大的应用程序,我会定期将ENTIRE调用堆栈记录到当前执行点(不是例外).这里的想法是,我想要一张确切的代码路径的地图,这使我成为我的观点.我一直在使用madExcept,使用jclDebug,虽然我可以获得一些调用堆栈,但我似乎无法获得在应用程序中进行的每个方法/过程/函数调用以显示在日志中.
我在项目中启用了堆栈帧,调试信息等.我甚至尝试在没有包含在调用堆栈中的各个方法上打开堆栈帧无济于事.
我正在努力做甚么可能吗?我真的试图避免在数百万行代码中添加日志代码以便记录代码路径.
我通过代码处理SIGSEGV:
int C()
{
int *i = NULL;
*i = 10; // Crash there
}
int B()
{
return C();
}
int A()
{
return B();
}
int main(void)
{
struct sigaction handler;
memset(&handler,0,sizeof(handler));
handler.sa_sigaction = handler_func;
handler.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV,&handler,NULL);
return(C());
}
Run Code Online (Sandbox Code Playgroud)
处理程序代码在哪里:
static int handler_func(int signal, siginfo_t info, void* rserved)
{
const void* stack[MAX_DEPTH];
StackCrowlState state;
state.addr = stack;
state.count = MAX_DEPTH;
_Unwind_Reason_Code code = _Unwind_Backtrace(trace_func,&state);
printf("Stack trace count: %d, code: %d\n",MAX_DEPTH - state.count, code);
kill(getpid(),SIGKILL);
}
static …Run Code Online (Sandbox Code Playgroud) 我的程序不断崩溃,但logcat没有显示任何异常.我只是得到以下消息,加上很多关于CPU使用率的统计信息.显然我使用了太多的CPU,但我不知道我的程序的哪个部分正在执行此操作.以下文件在哪里?我找不到它.
12-30 23:13:06.639:INFO/dalvikvm(7688):将堆栈跟踪写入'/data/anr/traces.txt'
我正在使用Clojure,我想抓住我可以记录的堆栈跟踪(理想情况下,我想将它作为String).
我看到它(.getStackTrace e)返回了一个,StackTraceElement[]但我不知道如何打印出有意义的东西.我的第二种方法是(.printStackTrace e)使用PrintWriter作为参数(因为我知道这在Java中是可行的),但我似乎没有得到正确的语法.
谢谢.
RUST_BACKTRACE=1 cargo run当发生错误时,done 会给出堆栈跟踪,如下所示.有没有办法获取文件和行号而不是十六进制地址?
thread '<main>' panicked at 'called `Result::unwrap()` on an `Err` value: Parsing: invalid encoding byte', /Users/rustbuild/src/rust-buildbot/slave/stable-dist-rustc-mac/build/src/libcore/result.rs:729
stack backtrace:
1: 0x104c9403f - sys::backtrace::write::h7807ec07859fb503t1r
2: 0x104c980e4 - panicking::on_panic::ha0ed2b9b562a7f9ctZv
3: 0x104c7c4d5 - rt::unwind::begin_unwind_inner::hbfb8d99cb52be7a1cHv
4: 0x104c7cd66 - rt::unwind::begin_unwind_fmt::hac7eda7c3f3b8498QFv
5: 0x104c979bc - rust_begin_unwind
6: 0x104cb75f5 - panicking::panic_fmt::h051633da0da2e362wwy
7: 0x104be0877 - result::Result<T, E>::unwrap::h15040486031244389916
8: 0x104bdc6f1 - main::h393644ca2d1fdb82uLa
9: 0x104c99e18 - rust_try_inner
10: 0x104c99e05 - rust_try
11: 0x104c988e8 - rt::lang_start::h5324dae87dacdac8YTv
12: 0x104be500e - main
An unknown error occurred
Run Code Online (Sandbox Code Playgroud) 我的应用程序的作用是显示通过windowManager.addView()和WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY标记附加的系统覆盖视图.这是通过服务完成的,该服务管理视图可见性和其他一些事情.
但是,我收到崩溃报告,无法重现它们.崩溃堆栈跟踪也与我的应用程序包无关,所以我真的无法解决这个问题的根源.以下是来自不同来源的两个堆栈跟踪,但似乎是相关的:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.measure(int, int)' on a null object reference
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2388)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2101)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1297)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7011)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:777)
at android.view.Choreographer.doCallbacks(Choreographer.java:590)
at android.view.Choreographer.doFrame(Choreographer.java:560)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:763)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Run Code Online (Sandbox Code Playgroud)
.
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getMeasuredWidth()' on a null object reference
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2484)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2181)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1293)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6599)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:800)
at android.view.Choreographer.doCallbacks(Choreographer.java:603)
at …Run Code Online (Sandbox Code Playgroud) 当我得到一个NPE时,我会得到一个带行号的堆栈跟踪.这很有用,但是如果行非常密集和/或包含嵌套表达式,那么仍然无法确定哪个引用为null.
当然,这些信息一定在某处可用.有没有办法解决这个问题?(如果不是java表达式,那么至少导致NPE的字节码指令也会有帮助)
编辑#1:我看过一些评论暗示分手等等,没有任何冒犯,实际上是非建设性和无关紧要的.如果我能做到这一点,我会的!我只想说修改源是不可能的.
编辑#2:apangin在下面发布了一个很好的答案,我接受了.但是,对于那些不想自己尝试的人来说,我必须将输出包含在这里!;)
假设我有这个驱动程序TestNPE.java
1 public class TestNPE {
2 public static void main(String[] args) {
3 int n = 0;
4 String st = null;
5
6 System.out.println("about to throw NPE");
7 if (n >= 0 && st.isEmpty()){
8 System.out.println("empty");
9 }
10 else {
11 System.out.println("othereise");
12 }
13 }
14
15 }
Run Code Online (Sandbox Code Playgroud)
字节码看起来像这样(仅显示main()方法并省略其他不相关的部分)
Code:
stack=2, locals=3, args_size=1
0: iconst_0
1: istore_1
2: aconst_null
3: astore_2
4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #3 // String …Run Code Online (Sandbox Code Playgroud) 有时回溯足以诊断问题.但是,如果没有知道传递给函数的内容,有时崩溃的原因并不明显.
获取传递给导致崩溃的函数的信息将非常有用,尤其是在再现不明显的情况下,因为它是由例如网络连接中的异常,奇怪的用户输入或者因为程序依赖于随机化或来自外部的处理数据引起的传感器.
可以说有以下程序
def handle_changed_input(changed_input)
raise 'ops' if changed_input =~ /magic/
end
def do_something_with_user_input(input)
input = "#{input.strip}c"
handle_changed_input(input)
end
input = gets
do_something_with_user_input(input)
Run Code Online (Sandbox Code Playgroud)
用户输入"magic"作为输入.通常一个人有
test.rb:2:in `handle_changed_input': ops (RuntimeError)
from test.rb:7:in `do_something_with_user_input'
from test.rb:11:in `<main>'
Run Code Online (Sandbox Code Playgroud)
作为输出.还有什么可以显示传递给函数的内容?就像是
test.rb:2:in `handle_changed_input("magic")': ops (RuntimeError)
from test.rb:7:in `do_something_with_user_input("magi\n")'
from test.rb:11:in `<main>'
Run Code Online (Sandbox Code Playgroud)
它在许多情况下都很有用(并且在参数不能表示为合理的字符串的情况下并不真正有用,因此有一个很好的理由为什么默认情况下不启用它).
如何添加此功能?程序必须在正常操作期间正常工作,并且优选地在崩溃之前没有额外的输出.
我试过这个例子
def do_something_with_user_input(input)
method(__method__).parameters.map do |_, name|
puts "#{name}=#{binding.local_variable_get(name)}"
end
raise 'ops' if input =~ /magic/
end
input = gets
Run Code Online (Sandbox Code Playgroud)
发现是否有办法在Ruby中访问方法参数?但它会打印在每个入口处,以便能够充分发挥输出功能并使程序显着变慢.