这个问题相当令人困惑。我试图弄清楚哪个变量没有正确返回。在将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);
}
}
}
在我知道这种类型的错误之前,我尝试将Res
和DynaSet
放在堆中而不是堆栈中,通过这样做:
static Result * ResPtr = NULL;
if(ResPtr != NULL)
{
delete ResPtr;
}
ResPtr = new Result();
这对这个问题没有帮助。以下变量周围的堆栈已损坏:Res
,DynaSet
我会尝试进一步缩小范围并尽快更新问题。
答案 0 :(得分:3)
这是非常可靠的诊断,VC6没有它。虚假警告的几率为零。请注意,在移植之前,您的代码库中可能存在此问题。它警告的错误非常严重,通常很难在没有帮助的情况下进行诊断。然而,它不一定是致命的问题,它可能潜伏在代码中很长一段时间。只是突然爆发出来,并以非常无辜的代码变化肆虐。只需使用Release构建设置重建程序就足够了,这使得诊断问题变得更加困难。
您的代码段太不透明而无法提出原因,未记录的函数可能会导致它。我只是描述诊断的工作方式,这样你就可以调试它。
/ RTC调试选项使编译器在堆栈帧中分配局部变量,以便它们之间有空格。它会生成一个标识这些空间的表。在函数入口处,这些空格用值0xcc填充。在函数出口处,它运行一个调试函数,该函数遍历表并检查这些空格是否仍包含0xcc。如果没有,你有一个非常可靠的指示,即代码正在写入它永远不应该触摸的堆栈帧位置。堆栈缓冲区溢出是一种可能性,还有其他可能性。
调试它的方法是使用Debug + Windows + Memory + Memory 1窗口。在函数的第一个语句处设置断点。当它命中时,将EBP放入地址栏并点击页面(注意堆栈增长)。您现在正在查看堆栈帧中的字节,切换到4字节视图通常是最好的。尝试将局部变量与您看到的值进行匹配。您还应该看到填充变量之间空格的0xcc值。现在使用调试器的StepOver命令开始步进。堆栈框架中更改的值以红色显示。尝试找到一个红色并且之前包含0xcc的那个。
您现在拥有一个被破坏的字节的地址。重新启动并使用数据断点使调试器停止在打包该字节的语句处。