1

我遇到了这个错误,我发现受欢迎

这个问题比较混乱。我试图找出哪个变量没有正确返回。这个问题是在将 VC6 项目移植到 VS 2012 时发现的。这里发生的情况是从数据库中获取记录集并转换为 XML。

CGenAction GenAct(lUserId, O_ALARM, A_GET_TREE, ppALResult)
{
    try
    {
        if (GenAct.BeginAction())
        {
            checkuserPremission(info);

            Result Res;
            Dynaset DynaSet;

            if (type.GetRecordSet(UserId, DynaSet, Res)) {
                turnToXml(DynaSet,Res.m_bstrXMLString);
            }

            returnToUI(Res);
        }
    }
}

在我知道这种类型的错误之前,我尝试通过执行以下操作将ResDynaSet放在堆中而不是堆栈中:

static Result * ResPtr = NULL;

if(ResPtr != NULL)
{
    delete ResPtr;           
}

ResPtr = new Result();

这无助于解决问题。以下变量周围的堆栈已损坏:ResDynaSet我将尝试进一步缩小范围并很快更新问题。

4

1 回答 1

3

这是一个非常可靠的诊断,VC6 没有。错误警告的几率为零。请注意,在您移植之前,这个问题很可能已经存在于您的代码库中。它警告的错误是一个非常严重的错误,通常在没有帮助的情况下很难诊断。然而,它不一定是一个致命的问题,它可以潜伏在代码中很长时间。只是突然弹出并通过看起来非常无辜的代码更改造成严重破坏。只需使用 Release 构建设置重新构建您的程序就足够了,这使得诊断问题变得更加困难。

您的代码片段太不透明,无法提出原因,未记录的功能很可能会导致它。我将只描述诊断的工作方式,以便您可以调试它。

/RTC 调试选项使编译器在堆栈帧中分配局部变量,因此它们之间有一个空间。它会生成一个标识这些空间的表。在函数入口处,这些空格用值 0xcc 填充。在函数退出时,它运行一个调试函数,遍历表并检查这些空间是否仍然包含 0xcc。如果没有,您将得到一个非常可靠的指示,表明代码正在写入它不应该触及的堆栈帧位置。堆栈缓冲区溢出是一种可能性,还有其他可能性。

调试它的方法是使用 Debug + Windows + Memory + Memory 1 窗口。在函数的第一条语句处设置断点。当它命中时,将 EBP 放入地址框并向上翻页(注意堆栈向下增长)。您现在正在查看堆栈帧中的字节,通常最好切换到 4 字节视图。尝试将局部变量与您看到的值相匹配。您还应该看到填充变量之间空格的 0xcc 值。现在开始单步执行,使用调试器的 StepOver 命令。堆栈帧中更改的值以红色显示。尝试找到之前为红色且包含 0xcc 的那个。

你现在有了一个被破坏的字节的地址。重新启动并使用数据断点让调试器在破坏该字节的语句处停止。

于 2013-04-24T12:52:58.347 回答