更改visual studio版本后,为什么我的功能会崩溃?

问题描述 投票:0回答:1

我在C ++中使用Visual Studio 2010编写了一个旧的32位MFC应用程序。它运行没有问题。现在我不得不升级到Visual Studio 2017,当我点击树视图窗口时,它经常崩溃。我有一个dmp文件,当我打开它然后我看到它在这里崩溃:

 BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
 {
     ENSURE(this != NULL);
     // it better be in valid memory, at least for CObject size
     ASSERT(AfxIsValidAddress(this, sizeof(CObject)));

     // simple SI case
         CRuntimeClass* pClassThis = GetRuntimeClass(); //---->HERE Crash 

     ENSURE(pClassThis);
     return pClassThis->IsDerivedFrom(pClass);
 }

当我回到通话清单然后我在这里结束:

//m_pTheModel is initialized with NULL
if (bValidValue == true)
    m_pTheModel = GetModel((WORD)lHint);

if (m_pTheModel == NULL || !AfxIsValidAddress(m_pTheModel, sizeof(m_pTheModel)))
{
   lock.Unlock();
   return;
}

try
{
    if ((m_pTheModel->IsKindOf(RUNTIME_CLASS(CMyClassModel))))
    ...
}
catch (...)
{
}

m_pTheModel不是NULL但是当我查看调试器中的值时,对于某些值,内存不可读。

问题是什么?随着旧版Visual Studio我没有遇到这个问题。我只重新编译了这个项目,我不得不将目标操作系统设置为Windows XP。

错误消息是“线程试图读取或写入其没有适当访问权限的虚拟地址”。

我也不明白为什么我不能用我的try-catch来捕获这个访问冲突。

更新:我找到了原因。覆盖我的指针是一个strcpy。

c++ visual-studio access-violation
1个回答
2
投票

使用AfxIsValidAddress非常令人担忧。

测试任何内存地址以确保它完全包含在程序的内存空间中。

更糟糕的是,它只适用于调试版本。

在非调试版本中,如果lp不为NULL,则为非零;否则为0。

这并不能保证它根本就是你想要的。如果删除一个对象,则内存可能仍在应用程序中,可以重用,而不是返回给操作系统,而AfxIsValidAddress之类的内容将返回true。更糟糕的是,当你的分配器确实重用了那个内存时,它仍然会返回true,而指针实际上现在指的是一些完全不同的未知对象,导致堆损坏。

这适用于所有类似的功能,如IsBadReadPtr。 Raymond Chen有一篇微软博客文章IsBadXxxPtr should really be called CrashProgramRandomly

你可能需要在IDE中调试它并找到一个特定的问题,它几乎可以肯定是在免费问题之后使用,或者是程序中其他地方覆盖对象的更严重的问题。你能直接在IDE中生成它而不是获取转储文件吗?

我也不明白为什么我不能用我的try-catch来捕获这个访问冲突

访问冲突等在各种平台上都不是C ++异常。而且由于它们通常只发生在程序内存损坏后,基本上无法从中恢复。通常有一些特定于平台的方法与它们进行交互。

© www.soinside.com 2019 - 2024. All rights reserved.