我正在调试一个程序(VS2008),我正在逐步调试代码.我遇到了一个调用委托函数的行,我试图进入它.但是,不是像我预期的那样进入方法,而是绕过了这个方法,调试器改为踩到我认为是委托调用的函数.在调用堆栈中,我期望委托方法的行用文本显示为灰色[Lightweight Function].
"轻量级功能"部分是什么意思?有没有办法进入这个功能?
多年来我在很多游戏项目中都使用过minidumps,他们似乎有大约50%的机会拥有一个有效的调用堆栈.我该怎么做才能让他们有更好的调用堆栈?
我已经尝试将最新的dbghelp.dll放在exe目录中.这似乎有些帮助.
Visual Studio 2008或2010是否更好?(我还在VS 2005).
我使用的代码看起来像这个样本.
注意这段代码:
#include <stdio.h>
void a(int a, int b, int c)
{
    char buffer1[5];
    char buffer2[10];
}
int main()
{
    a(1,2,3); 
}
之后 :
gcc -S a.c
该命令在程序集中显示我们的源代码.
现在我们可以在main函数中看到,我们从不使用"push"命令将函数的参数压入堆栈.它用"movel"而不是那个
main:
 pushl %ebp
 movl %esp, %ebp
 andl $-16, %esp
 subl $16, %esp
 movl $3, 8(%esp)
 movl $2, 4(%esp)
 movl $1, (%esp)
 call a
 leave
为什么会这样?他们之间有什么区别?
为什么下面的代码没有任何崩溃@ runtime?
而且尺寸完全取决于机器/平台/编译器!! 我甚至可以在64位机器上放弃200.如何在OS中检测到主函数中的分段错误?
int main(int argc, char* argv[])
{
    int arr[3];
    arr[4] = 99;
}
这个缓冲空间来自哪里?这是分配给进程的堆栈吗?
有没有办法让chrome dev工具中的调用堆栈面板崩溃?每当我遇到断点时它会扩展,迫使我向下滚动到范围.这使调试非常缓慢,有时令人愤怒.
谢谢/埃里克
我曾经在嵌入式系统的项目上工作过,我们重新安排了堆栈变量声明的顺序,以减少生成的可执行文件的大小.例如,如果我们有:
void func()
{
    char c;
    int i;
    short s;
    ...
}
我们会将此重新排序为:
void func()
{
    int i;
    short s;
    char c;
    ...
}
由于对齐问题,第一个导致使用12个字节的堆栈空间,第二个导致仅8个字节.
这是C编译器的标准行为,还是我们使用的编译器的缺点?
在我看来,编译器应该能够重新排序堆栈变量,以便在需要时支持更小的可执行文件大小.有人向我建议,C标准的某些方面可以防止这种情况,但我无法以任何方式找到信誉良好的来源.
作为一个额外的问题,这也适用于C++编译器吗?
编辑
如果答案是肯定的,那么C/C++编译器可以重新排列堆栈变量,你能给出一个肯定会这样做的编译器的例子吗?我想看看编译器文档或类似的东西支持这一点.
再次编辑
谢谢大家的帮助.对于文档,我能够找到的最好的东西是GCC(pdf)中的最佳堆栈槽分配,由Naveen Sharma和Sanjiv Kumar Gupta撰写,于2003年在海湾合作委员会峰会会议上提交.
这里讨论的项目是使用ADS编译器进行ARM开发.在该编译器的文档中提到,像我所示的排序声明可以提高性能以及堆栈大小,因为ARM-Thumb架构如何计算本地堆栈帧中的地址.该编译器没有自动重新排列本地人以利用这一点.这里链接的论文说,截至2003年,GCC也没有重新安排堆栈帧以改善ARM-Thumb处理器的参考局部性,但它暗示你可以.
我找不到任何明确表示这在GCC中实施过的东西,但我认为这篇论文可以证明你是正确的.再次感谢.
我在软件中遇到了一个奇怪的崩溃,我在调试它时遇到了很多麻烦,因此我正在寻求如何解决它的建议.
崩溃是读取NULL指针的访问冲突:
$ 00CF0041的第一次机会异常.异常类$ C0000005,消息'访问冲突位于0x00cf0041:读取地址0x00000000'.
它只发生'有时' - 我还没有设法找出任何押韵或理由,但是,当时 - 并且只在主线程中.当它发生时,调用堆栈包含一个不正确的条目:

对于主线程,它应该显示一个充满其他项目的大堆栈.
此时,所有其他线程都处于非活动状态(主要是坐在WaitForSingleObject或类似的功能.)我只看到这个崩溃发生在主线程中.它始终具有一个条目的相同调用堆栈,在同一地址的相同方法中.此方法可能相关也可能不相关 - 我们在应用程序中使用VCL.不过,我的赌注是,某些东西(可能是很久以前)正在破坏堆栈,而崩溃的地址实际上是随机的.请注意,它在几个版本中的地址相同 - 但它可能不是真正随机的.
这是我尝试过的:
我的问题:
1.如何找到导致崩溃的代码?我怎么做相当于走回堆栈?
2.对于如何追踪此次崩溃的原因,您有什么一般性的建议?
我正在使用Embarcadero RAD Studio 2010(该项目主要包含C++ Builder代码和少量Delphi.)
编辑:我想我应该添加实际导致这个的东西.有一个线程调用ReadDirectoryChangesW然后,使用GetOverlappedResult,等待事件继续并对更改执行某些操作.事件也发出信号,以便在设置状态标志后终止线程.问题是当线程退出时它从未调用过CancelIO.因此,Windows仍在跟踪更改,并且可能仍然在目录更改时写入缓冲区,即使缓冲区,重叠的结构和事件不再存在(也没有创建它们的线程上下文.)CancelIO调用时,没有更多的崩溃.
在上一个问题(获取对象调用层次结构)中,我得到了这个有趣的答案:
调用堆栈不是告诉你你来自哪里.它是告诉你下一步的去向.
据我所知,当到达函数调用时,程序通常会执行以下操作:
在调用代码时:
在被叫目标代码中:
返回过程:撤消我们调用函数时所做的操作,即展开/弹出调用堆栈:
题:
如何将其视为"告诉您下一步的去向"而不是"告诉您从何而来"?
在C#的JIT或C#的运行时环境中是否存在使得调用堆栈以不同方式工作的东西?
感谢有关调用堆栈描述的文档的任何指示 - 有大量关于传统调用堆栈如何工作的文档.
这很容易解释:这很有效
using System;
using ConstraintSet = System.Collections.Generic.Dictionary<System.String, double>;
namespace ConsoleApplication2
{
    class test
    {
        public ConstraintSet a { get; set; }
        public test()
        {
            a = new ConstraintSet();
        }
        static void Main(string[] args)
        {
            test abc = new test();
            Console.WriteLine("done");
        }
    }
}
这不
using System;
using ConstraintSet = System.Collections.Generic.Dictionary<System.String, double>;
namespace ConsoleApplication2
{
    class test
    {
        public ConstraintSet a { get { return a; } set { a = value; } }
        public test()
        {
            a = new ConstraintSet(); …