- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
有时,当我从应用程序获得崩溃报告时,堆栈跟踪中缺少一个方法。我认为以下代码不会重现它,但可以说,我们有以下代码供引用:
using System.IO;
using System;
using System.Collections.Generic;
class Program
{
static List<int> stuff;
static void Main()
{
stuff = new List<int>();
int result = Foo();
}
static int Foo(){
return Bar(5);
}
static int Bar(int value){
return stuff[value];
}
}
当 System.Collections.Generic.List'1.get_Item(Int32 index)
抛出 System.ArgumentOutOfRangeException
时,堆栈跟踪丢失 Foo()
。为了这个论点,编译器没有优化代码,因为反编译器显示它不是内联的。有谁知道什么会导致这种情况(编译器内联除外)?
编辑:需要澄清的是,在进行堆栈跟踪时,应用程序并未处于 Debug模式。
最佳答案
TL;DR:这些方法是由 JIT 而非编译器内联的,那么您只能在 ASM
中看到它拆卸,不在MSIL
反汇编。
让我们在 Debug模式下编译你的代码,现在让我们反编译 MSIL
.
结果看起来不错:
namespace ConsoleTests
{
using System;
using System.Collections.Generic;
internal class Program
{
private static List<int> stuff;
private static int Bar(int value)
{
return stuff[value];
}
private static int Foo()
{
return Bar(5);
}
private static void Main()
{
stuff = new List<int>();
int num = Foo();
}
}
}
调用堆栈也已完成:
Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
at System.Collections.Generic.List`1.get_Item(Int32 index)
at ConsoleTests.Program.Bar(Int32 value) in C:\Users\Some1Pr0\documents\visual studio 2015\Projects\ConsoleTests\ConsoleTests\Program.cs:line 40
at ConsoleTests.Program.Foo() in C:\Users\Some1Pr0\documents\visual studio 2015\Projects\ConsoleTests\ConsoleTests\Program.cs:line 35
at ConsoleTests.Program.Main() in C:\Users\Some1Pr0\documents\visual studio 2015\Projects\ConsoleTests\ConsoleTests\Program.cs:line 30
现在让我们在发布中编译:
现在我们可以看到调用堆栈不完整:
Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
at ConsoleTests.Program.Main() in C:\Users\Some1Pr0\documents\visual studio 2015\Projects\ConsoleTests\ConsoleTests\Program.cs:line 30
另外,VS2015
的调试器|无法进入 Foo
.
让我们检查一下 MSIL
:
namespace ConsoleTests
{
using System;
using System.Collections.Generic;
internal class Program
{
private static List<int> stuff;
private static int Bar(int value)
{
return stuff[value];
}
private static int Foo()
{
return Bar(5);
}
private static void Main()
{
stuff = new List<int>();
Foo();
}
}
}
显然代码看起来是一样的,所以让我们更深入地检查一下 JITTED
assembly
代码。
如果我们查看调试版本的反汇编,我们会看到整个代码都在那里,包括完整的JITTED
。方法:
00007FFDD8AF4722 56 push rsi
00007FFDD8AF4723 48 83 EC 40 sub rsp,40h
00007FFDD8AF4727 48 8B EC mov rbp,rsp
00007FFDD8AF472A 48 8D 7D 24 lea rdi,[rbp+24h]
00007FFDD8AF472E B9 07 00 00 00 mov ecx,7
00007FFDD8AF4733 33 C0 xor eax,eax
00007FFDD8AF4735 F3 AB rep stos dword ptr [rdi]
00007FFDD8AF4737 48 B8 00 4F B3 D8 FD 7F 00 00 mov rax,7FFDD8B34F00h
00007FFDD8AF4741 83 38 00 cmp dword ptr [rax],0
00007FFDD8AF4744 74 05 je 00007FFDD8AF474B
00007FFDD8AF4746 E8 B1 17 AB 5F call 00007FFE385A5EFC
00007FFDD8AF474B 90 nop
29: stuff = new List<int>();
00007FFDD8AF474C 48 B9 28 F1 1F 37 FE 7F 00 00 mov rcx,7FFE371FF128h
00007FFDD8AF4756 E8 65 01 63 5F call 00007FFE381248C0
00007FFDD8AF475B 48 89 45 28 mov qword ptr [rbp+28h],rax
00007FFDD8AF475F 48 8B 4D 28 mov rcx,qword ptr [rbp+28h]
00007FFDD8AF4763 E8 E8 0E E7 5E call 00007FFE37965650
00007FFDD8AF4768 48 B9 70 85 6C D9 63 00 00 00 mov rcx,63D96C8570h
00007FFDD8AF4772 48 8B 55 28 mov rdx,qword ptr [rbp+28h]
00007FFDD8AF4776 E8 85 CD 62 5F call 00007FFE38121500
30: int result = Foo();
00007FFDD8AF477B E8 F0 C7 FF FF call 00007FFDD8AF0F70
00007FFDD8AF4780 89 45 24 mov dword ptr [rbp+24h],eax
00007FFDD8AF4783 8B 45 24 mov eax,dword ptr [rbp+24h]
00007FFDD8AF4786 89 45 34 mov dword ptr [rbp+34h],eax
31: }
00007FFDD8AF4789 90 nop
00007FFDD8AF478A 48 8D 65 40 lea rsp,[rbp+40h]
00007FFDD8AF478E 5E pop rsi
00007FFDD8AF478F 5F pop rdi
00007FFDD8AF4790 5D pop rbp
00007FFDD8AF4791 C3 ret
34: {
00007FFDD8AF47B0 55 push rbp
00007FFDD8AF47B1 57 push rdi
00007FFDD8AF47B2 56 push rsi
00007FFDD8AF47B3 48 83 EC 30 sub rsp,30h
00007FFDD8AF47B7 48 8B EC mov rbp,rsp
00007FFDD8AF47BA 48 8D 7D 20 lea rdi,[rbp+20h]
00007FFDD8AF47BE B9 04 00 00 00 mov ecx,4
00007FFDD8AF47C3 33 C0 xor eax,eax
00007FFDD8AF47C5 F3 AB rep stos dword ptr [rdi]
00007FFDD8AF47C7 48 B8 00 4F B3 D8 FD 7F 00 00 mov rax,7FFDD8B34F00h
00007FFDD8AF47D1 83 38 00 cmp dword ptr [rax],0
00007FFDD8AF47D4 74 05 je 00007FFDD8AF47DB
00007FFDD8AF47D6 E8 21 17 AB 5F call 00007FFE385A5EFC
00007FFDD8AF47DB 90 nop
35: return Bar(5);
00007FFDD8AF47DC B9 05 00 00 00 mov ecx,5
00007FFDD8AF47E1 E8 92 C7 FF FF call 00007FFDD8AF0F78
00007FFDD8AF47E6 89 45 20 mov dword ptr [rbp+20h],eax
00007FFDD8AF47E9 8B 45 20 mov eax,dword ptr [rbp+20h]
00007FFDD8AF47EC 89 45 24 mov dword ptr [rbp+24h],eax
00007FFDD8AF47EF 90 nop
00007FFDD8AF47F0 EB 00 jmp 00007FFDD8AF47F2
36: }
00007FFDD8AF47F2 8B 45 24 mov eax,dword ptr [rbp+24h]
00007FFDD8AF47F5 48 8D 65 30 lea rsp,[rbp+30h]
00007FFDD8AF47F9 5E pop rsi
00007FFDD8AF47FA 5F pop rdi
00007FFDD8AF47FB 5D pop rbp
00007FFDD8AF47FC C3 ret
34: {
00007FFDD8AF47B2 56 push rsi
00007FFDD8AF47B3 48 83 EC 30 sub rsp,30h
00007FFDD8AF47B7 48 8B EC mov rbp,rsp
00007FFDD8AF47BA 48 8D 7D 20 lea rdi,[rbp+20h]
00007FFDD8AF47BE B9 04 00 00 00 mov ecx,4
00007FFDD8AF47C3 33 C0 xor eax,eax
00007FFDD8AF47C5 F3 AB rep stos dword ptr [rdi]
00007FFDD8AF47C7 48 B8 00 4F B3 D8 FD 7F 00 00 mov rax,7FFDD8B34F00h
00007FFDD8AF47D1 83 38 00 cmp dword ptr [rax],0
00007FFDD8AF47D4 74 05 je 00007FFDD8AF47DB
00007FFDD8AF47D6 E8 21 17 AB 5F call 00007FFE385A5EFC
00007FFDD8AF47DB 90 nop
35: return Bar(5);
00007FFDD8AF47DC B9 05 00 00 00 mov ecx,5
00007FFDD8AF47E1 E8 92 C7 FF FF call 00007FFDD8AF0F78
00007FFDD8AF47E6 89 45 20 mov dword ptr [rbp+20h],eax
00007FFDD8AF47E9 8B 45 20 mov eax,dword ptr [rbp+20h]
00007FFDD8AF47EC 89 45 24 mov dword ptr [rbp+24h],eax
00007FFDD8AF47EF 90 nop
00007FFDD8AF47F0 EB 00 jmp 00007FFDD8AF47F2
36: }
00007FFDD8AF47F2 8B 45 24 mov eax,dword ptr [rbp+24h]
00007FFDD8AF47F5 48 8D 65 30 lea rsp,[rbp+30h]
00007FFDD8AF47F9 5E pop rsi
00007FFDD8AF47FA 5F pop rdi
00007FFDD8AF47FB 5D pop rbp
00007FFDD8AF47FC C3 ret
39: {
00007FFDD8AF4820 55 push rbp
00007FFDD8AF4821 57 push rdi
00007FFDD8AF4822 56 push rsi
00007FFDD8AF4823 48 83 EC 30 sub rsp,30h
00007FFDD8AF4827 48 8B EC mov rbp,rsp
00007FFDD8AF482A 48 8B F1 mov rsi,rcx
00007FFDD8AF482D 48 8D 7D 20 lea rdi,[rbp+20h]
00007FFDD8AF4831 B9 04 00 00 00 mov ecx,4
00007FFDD8AF4836 33 C0 xor eax,eax
00007FFDD8AF4838 F3 AB rep stos dword ptr [rdi]
00007FFDD8AF483A 48 8B CE mov rcx,rsi
00007FFDD8AF483D 89 4D 50 mov dword ptr [rbp+50h],ecx
00007FFDD8AF4840 48 B8 00 4F B3 D8 FD 7F 00 00 mov rax,7FFDD8B34F00h
00007FFDD8AF484A 83 38 00 cmp dword ptr [rax],0
00007FFDD8AF484D 74 05 je 00007FFDD8AF4854
00007FFDD8AF484F E8 A8 16 AB 5F call 00007FFE385A5EFC
00007FFDD8AF4854 90 nop
40: return stuff[value];
00007FFDD8AF4855 48 B9 70 85 6C D9 63 00 00 00 mov rcx,63D96C8570h
00007FFDD8AF485F 48 8B 09 mov rcx,qword ptr [rcx]
00007FFDD8AF4862 8B 55 50 mov edx,dword ptr [rbp+50h]
00007FFDD8AF4865 39 09 cmp dword ptr [rcx],ecx
00007FFDD8AF4867 E8 94 0C E7 5E call 00007FFE37965500
00007FFDD8AF486C 89 45 20 mov dword ptr [rbp+20h],eax
00007FFDD8AF486F 8B 45 20 mov eax,dword ptr [rbp+20h]
00007FFDD8AF4872 89 45 24 mov dword ptr [rbp+24h],eax
00007FFDD8AF4875 90 nop
00007FFDD8AF4876 EB 00 jmp 00007FFDD8AF4878
41: }
00007FFDD8AF4878 8B 45 24 mov eax,dword ptr [rbp+24h]
00007FFDD8AF487B 48 8D 65 30 lea rsp,[rbp+30h]
00007FFDD8AF487F 5E pop rsi
00007FFDD8AF4880 5F pop rdi
00007FFDD8AF4881 5D pop rbp
00007FFDD8AF4882 C3 ret
但是当我们检查发布版本时,我们可以看到它确实是内联的(由JIT
- 而不是由编译器) 我们可以在 Main
中看到列表索引器的绑定(bind)检查方法:
29: stuff = new List<int>();
00007FFDD8AD4102 83 EC 20 sub esp,20h
00007FFDD8AD4105 48 B9 28 F1 1F 37 FE 7F 00 00 mov rcx,7FFE371FF128h
00007FFDD8AD410F E8 AC 07 65 5F call 00007FFE381248C0
00007FFDD8AD4114 48 8B F0 mov rsi,rax
00007FFDD8AD4117 B9 01 00 00 00 mov ecx,1
00007FFDD8AD411C BA 43 00 00 00 mov edx,43h
00007FFDD8AD4121 E8 46 0A 7B 5F call 00007FFE38284B6C
00007FFDD8AD4126 48 BA 60 89 E1 2D 69 00 00 00 mov rdx,692DE18960h
00007FFDD8AD4130 48 8B 12 mov rdx,qword ptr [rdx]
00007FFDD8AD4133 48 8D 4E 08 lea rcx,[rsi+8]
00007FFDD8AD4137 E8 F4 D3 64 5F call 00007FFE38121530
00007FFDD8AD413C 48 B9 60 85 E1 2D 69 00 00 00 mov rcx,692DE18560h
00007FFDD8AD4146 48 8B D6 mov rdx,rsi
00007FFDD8AD4149 E8 B2 D3 64 5F call 00007FFE38121500
30: int result = Foo();
00007FFDD8AD414E 48 B9 60 85 E1 2D 69 00 00 00 mov rcx,692DE18560h
00007FFDD8AD4158 48 8B 31 mov rsi,qword ptr [rcx]
00007FFDD8AD415B 83 7E 18 05 cmp dword ptr [rsi+18h],5
//-------------------------------------------------------------------------
00007FFDD8AD415F 77 0F ja 00007FFDD8AD4170 //BOUND CHECK!!!!!
//-------------------------------------------------------------------------
00007FFDD8AD4161 B9 0D 00 00 00 mov ecx,0Dh
00007FFDD8AD4166 BA 16 00 00 00 mov edx,16h
00007FFDD8AD416B E8 A0 2C D2 5E call 00007FFE377F6E10 //EXCEPTION
00007FFDD8AD4170 48 8B 46 08 mov rax,qword ptr [rsi+8]
00007FFDD8AD4174 83 78 08 05 cmp dword ptr [rax+8],5
00007FFDD8AD4178 76 09 jbe 00007FFDD8AD4183
00007FFDD8AD417A 8B 40 24 mov eax,dword ptr [rax+24h]
00007FFDD8AD417D 48 83 C4 20 add rsp,20h
00007FFDD8AD4181 5E pop rsi
00007FFDD8AD4182 C3 ret
00007FFDD8AD4183 E8 50 45 AD 5F call 00007FFE385A86D8
00007FFDD8AD4188 CC int 3
关于c# - 异常堆栈跟踪丢失的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20505160/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!