目前,C ++编写的程序抛出一个异常,并在windows下运行。
这是日志中的最小转储信息。
08/12/15 04:37:19 I New Information for UID 2d936a, FloorLoc F1505
08/12/15 04:37:19 E >>>>> EXCEPTION: Access Violation while trying to read address 20203567
[Fault address: 004AF945 01:000AE945 C:\Program Files (x86)\MySystems\WPR.exe 00400000] <<<<<
Call stack:
Load addr Address Frame Logical addr Module
00400000 004AF945 0588F8CC 0001:000AE945 C:\Program Files (x86)\MySystems\WPR.exe
00400000 004A89A4 0588FAEC 0001:000A79A4 C:\Program Files (x86)\MySystems\WPR.exe
根据逻辑地址和.map
文件,我可以找到引发此异常的代码。
if (TempMSE->m_elem == NULL)
{
TempMSE->m_elem = new Element(element);
TempMSE->m_elem->SetLocation(FloorLoc);
LoggerInfo("New Information for UID %x, FloorLoc %s", Id, FloorLoc.ToString(buf));
}
TempMSE->m_elem->SetValue0(CIN_0, 0); // this exception is thrown here!!! through logical address 0001:000AE945
似乎m_elem
从new
运算符获取一个地址,SetLocation
函数调用没有异常。以下日志输出也正确。
为什么SetValue0
引发了一个例外?这是函数SetValue0
void SetValue0(INDEX idx, DWORD val)
{
if (idx >= 0 && idx < MAX_INDEX){
if(val != m_Info[idx])
{
m_Info[idx] = val;
}
}
}
m_Info
是Element
中的一个数组变量,其大小为MAX_INDEX
。
另一方面,地址0x20203567
似乎是一个可读的地址,怎么会被读取违规?
修改
在此处添加更多信息
class Element {
// other function here...
private:
FloorLocation m_FloorLoc;
DWORD m_Info[MAX_INDEX];
bool m_Dirty;
};
Element::Element(const Element& elem) {
m_FloorLoc = elem.m_FloorLoc;
for (int i = 0; i < MAX_INDEX; ++i)
m_Info[i] = elem.m_Info[i];
m_Dirty = elem.m_Dirty;
}
class FloorLocation {
// other function here...
private:
FloorId m_floorloc;
};
FloorLocation::FloorLocation( const FloorLocation& loc )
{
memset(&m_floorloc, ' ', 8); // space filled
if(loc.m_floorloc.id[0] != 0)
{
memcpy(m_floorloc.id, loc.m_floorloc.id, 8);
// eliminate nulls
for(int ndx=0; ndx < 8; ndx++)
{
if(m_floorloc.id[ndx] == 0)
m_floorloc.id[ndx]=' ';
}
}
}
typedef struct {
char id[8];
} FloorId;
答案 0 :(得分:1)
这些问题有点难以回答。我在评论中提出了一些想法,我将在这里详细说明。当我有这些种类的崩溃日志而没有其他线索时,我会寻找这些东西。
在该位置读取的访问冲突建议执行以下操作之一:
TempMSE
不是有效指针,尝试从中获取m_elem
时会抛出异常;
TempMSE->m_elem
无效,尝试测试SetValue0
的值时会在m_Info[idx]
内抛出异常。
在后一种情况下,如果您在某处删除TempMSE->m_elem
但未将其设置为NULL,则可能会发生这种情况。如果另一个线程负责该删除,可能你在这里有一个竞争条件,它将被设置为NULL,但是这个代码首先被执行。
另一种可能性是TempMSE
或TempMSE->m_elem
在此过程中的任何地方都会被破坏。这可能是TempMSE
内部缓冲区溢出(如果您有数组)的结果,或者基本上是在内存中这些指针附近发生的任何类型的未定义行为。如果TempMSE
在堆栈中,那么在那里寻找任何潜在的麻烦。
我不想用其他类型的猜测(比如堆损坏)来填补这个答案,但希望它能给你一些尝试的途径。常见罪魁祸首的基本清单如下:
答案 1 :(得分:1)
我不能说实际上有什么错误,但是我会在0x004AF945
处反编译代码 - 以及之前的几条指令,并尝试理解失败函数的哪一部分。
正如其中一条评论所指出的那样,故障发生的地址可疑地看起来像'C# '
,这让我觉得某个字符串溢出某个地方......
这只是猜测,但我怀疑TempMSE->m_elem
是包含值0x20203567
的内容,因此在尝试访问它时不是NULL
,这意味着不执行任何日志记录。 [显然这是基于你到目前为止所显示的代码,如果在该节目之前/之后有记录,则不是这种情况,我的第二个猜测是m_info
在某种程度上是错误的......