Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 无法追踪?尽管已检查是否存在此=nullptr的访问冲突_C++_Assembly_Stack Trace_Access Violation - Fatal编程技术网

C++ 无法追踪?尽管已检查是否存在此=nullptr的访问冲突

C++ 无法追踪?尽管已检查是否存在此=nullptr的访问冲突,c++,assembly,stack-trace,access-violation,C++,Assembly,Stack Trace,Access Violation,我正在分析一个相当复杂的项目中罕见但持续的崩溃,这是一个“不可能的堆栈跟踪”,意思是:第一眼和第二眼,一切看起来都很好 崩溃本身是“引发未处理的异常:读取访问冲突。这是nullptr。” 堆栈当前帧处的代码如下所示: FT6VehiclePathCheckpoint AT6Building::GetVehicleCheckpoint() const { FT6VehiclePathCheckpoint targetCheckpoint = FT6VehiclePathCheckpoint

我正在分析一个相当复杂的项目中罕见但持续的崩溃,这是一个“不可能的堆栈跟踪”,意思是:第一眼和第二眼,一切看起来都很好

崩溃本身是“引发未处理的异常:读取访问冲突。这是nullptr。”

堆栈当前帧处的代码如下所示:

FT6VehiclePathCheckpoint AT6Building::GetVehicleCheckpoint() const
{
    FT6VehiclePathCheckpoint targetCheckpoint = FT6VehiclePathCheckpoint();
    if (GetBusStopComponent() != nullptr)
    {
        ...
const AT6Building* portalBuildingByLocation = pathFinder != nullptr ? pathFinder->GetPortalBuildingByLocation(startLocation) : GetNearestDrivewayBuilding();

if (portalBuildingByLocation != nullptr)
{
    startCheckpoint = portalBuildingByLocation->GetVehicleCheckpoint();
}
崩溃在“if(GetBusStopComponent()!=nullptr)”行中。函数“GetBusStopComponent()”本身是对象成员变量的内联getter,因此它不会显示在跟踪中。另外,在内存转储中,“this”实际上是0。到目前为止还不错

但是,其正上方的堆栈帧如下所示:

FT6VehiclePathCheckpoint AT6Building::GetVehicleCheckpoint() const
{
    FT6VehiclePathCheckpoint targetCheckpoint = FT6VehiclePathCheckpoint();
    if (GetBusStopComponent() != nullptr)
    {
        ...
const AT6Building* portalBuildingByLocation = pathFinder != nullptr ? pathFinder->GetPortalBuildingByLocation(startLocation) : GetNearestDrivewayBuilding();

if (portalBuildingByLocation != nullptr)
{
    startCheckpoint = portalBuildingByLocation->GetVehicleCheckpoint();
}
(指向行“portalBuildingByLocation->GetVehicleCheckpoint”)。很明显,在调用函数之前有一个nullptr检查。这是第一眼

接下来,我怀疑“GetVehicleCheckpoint”中有内存损坏,这会破坏堆栈跟踪?但实际上什么都没有。“FT6VehiclePathCheckpoint”初始化甚至没有构造函数——只有一堆直接初始化的字段(它们都类似于nullptr和整数文本)

代码是用cl.exe编译的,并且启用了优化,所以我怀疑我在某个地方得到了一些UB,编译器依赖于某些东西

所以,尽管在阅读汇编代码方面我是个呆子,但我还是尝试了。这是GetVehicleCheckpoint函数的第一部分:

FT6VehiclePathCheckpoint AT6Building::GetVehicleCheckpoint() const
{
00007FF7304714B0  mov         qword ptr [rsp+8],rbx  
00007FF7304714B5  mov         qword ptr [rsp+10h],rsi  
00007FF7304714BA  push        rdi  
00007FF7304714BB  sub         rsp,40h  
    FT6VehiclePathCheckpoint targetCheckpoint = FT6VehiclePathCheckpoint();
00007FF7304714BF  xor         eax,eax  
00007FF7304714C1  mov         qword ptr [rsp+28h],0FFFFFFFFFFFFFFFFh  
00007FF7304714CA  mov         qword ptr [rsp+30h],rax  
00007FF7304714CF  mov         rsi,rcx  

    if (GetBusStopComponent() != nullptr)
00007FF7304714D2  mov         rcx,qword ptr [rcx+5F8h]  
最后一行发生了车祸。好的,如果我理解正确的话,它试图从rcx+5F8h读取一个qword,并且很可能rcx是0?(如果是这样的话,那么错误不应该是“访问冲突,试图从0x5f8读取”吗?嗯,也许visual studio想提供更多帮助….)

此外,我还验证了:BusStopComponent确实位于类的偏移量0x5F8处

好的,我试着将rcx追踪到倒数第二帧:

            const AT6Building* portalBuildingByLocation = pathFinder != nullptr ? pathFinder->GetPortalBuildingByLocation(startLocation) : GetNearestDrivewayBuilding();
00007FF730410F21  lea         rdx,[rbp-29h]  
00007FF730410F25  mov         rcx,r12  
00007FF730410F28  call        AT6AStarPathfinder::GetPortalBuildingByLocation (07FF73059CD30h)  
00007FF730410F2D  jmp         UT6Agent::HandleAgentArrivedToUseCar+34Ah (07FF730410F4Ah)  
00007FF730410F2F  test        r12,r12  
00007FF730410F32  je          UT6Agent::HandleAgentArrivedToUseCar+342h (07FF730410F42h)  
00007FF730410F34  lea         rdx,[rbp-29h]  
00007FF730410F38  mov         rcx,r12  
00007FF730410F3B  call        AT6AStarPathfinder::GetPortalBuildingByLocation (07FF73059CD30h)  
00007FF730410F40  jmp         UT6Agent::HandleAgentArrivedToUseCar+34Ah (07FF730410F4Ah)  
00007FF730410F42  mov         rcx,rsi  
00007FF730410F45  call        UT6Agent::GetNearestDrivewayBuilding (07FF73040DA50h)  

            if (portalBuildingByLocation != nullptr)
00007FF730410F4A  test        rax,rax  
00007FF730410F4D  je          UT6Agent::HandleAgentArrivedToUseCar+36Ch (07FF730410F6Ch)  
            {
                startCheckpoint = portalBuildingByLocation->GetVehicleCheckpoint();
00007FF730410F4F  mov         rcx,rax  
00007FF730410F52  lea         rdx,[rbp-9]  
00007FF730410F56  call        AT6Building::GetVehicleCheckpoint (07FF7304714B0h)  
00007FF730410F5B  movups      xmm0,xmmword ptr [rax]  
再次声明:我对解释程序集不是很有信心,但仅通过目测,我看到rcx被设置为rax中的任何值,并且rax被正确地测试为0。因此,“编译器在优化过程中删除了nullptr检查”这一说法并不奇怪

有什么见解会导致访问违规吗?有什么可疑的东西能给我线索吗

干杯,伊米。

明白了!(或者更确切地说是大卫·沃尔弗德发现的)

“直接在上面的堆栈帧”有误导性,因为代码在同一个函数中多次重复使用此调用(在不同的if分支中)。当查看局部变量时,那里的分支路径实际上是不可能的,我将问题确定为另一个数组中的nullptr


感谢大卫·沃尔弗德!死定了!:)

嗯。。理论:对GetNearestDrivewayBuilding的调用是否会扰乱其堆栈帧的返回地址,并通过nullptr检查“希望”恰好调用GetVehicleCheckpoint?如果这是Visual Studio,您应该能够看到寄存器值(它们有一个调试窗口)。rcx和rsi可能很有趣。为地址rcx或rcx+5F8h打开一个内存窗口也可能提供信息,因为您可以检查该类的所有成员变量。逐个检查它们可能没有效果(考虑到有5f8h字节的价值),但要看看它是否通常是正确的,尤其是在5f8h偏移量附近。RCX确实是0。在第二个堆栈帧中,RSI为0x229239866E0(在最低堆栈帧中,在“mov RSI,rcx”之后,RSI也为0)。但是这个内存位置似乎不是崩溃转储的一部分:(-I get all??当在内存调试中直接查看它时(我假设这是因为外部的“this”位于堆上,并且它是一个“小崩溃转储”)。或者RSI中的值是对某个其他值的偏移量吗?例如,
RelatedPathBuildings[CurrentPath.CurrentSegmentIndex]
为空?虽然我从未这样做过,但如果(this==nullptr)\uu debugbreak()在GetVehicleCheckpoint内。及早发现问题可能会让您在被覆盖之前看到更多内容。@DavidWohlferd:IIRC,在
nullptr
上调用成员函数很不幸是UB,因此允许编译器假设它为非null并优化掉该检查,并在实践中这样做。在未优化的构建中,您可以不过,我们还是可以通过调试来解决这个问题。