在 Visual C++ 2005 中开发的 Visual C++ 项目 - 在 Visual C++ 2010 中,打开菜单时调试断言失败,但发布模式有效,如何解决?

Posted

技术标签:

【中文标题】在 Visual C++ 2005 中开发的 Visual C++ 项目 - 在 Visual C++ 2010 中,打开菜单时调试断言失败,但发布模式有效,如何解决?【英文标题】:Visual C++ project developed in Visual C++ 2005 - In Visual C++ 2010, debug assertion fails on menu open, but release mode works, how to fix? 【发布时间】:2011-08-12 00:02:57 【问题描述】:

我刚开始从事一个项目,该项目是由其他人在 Visual C++ 2005 中使用 MFC 开发的。为此,我安装了 Visual C++ 2010 - 我没有使用任何一个版本(或 Visual Studio,就此而言)的经验。

应用程序有一个使用CMenu 类实现的菜单栏,并从资源初始化(即使用菜单编辑器创建)。

如果我在调试模式下运行应用程序,只要我打开菜单栏中的任何菜单,以下调试断言就会失败:

文件名:afxwin1.inl

断言(带有适当的上下文):



    _AFXWIN_INLINE HMENU CMenu::GetSafeHmenu() const
         ASSERT(this == NULL || m_hMenu == NULL || ::IsMenu(m_hMenu));
            return this == NULL ? NULL : m_hMenu; 

根据调试器,this 设置为指向我的菜单的指针,this->m_hMenu 也设置为指针 - 但是,调试器似乎对类型感到困惑,值为 0xdeadbeef unused=??? (当然是更无聊的0xdeadbeef)。

似乎有些东西坏了,而且很可能在项目代码中 - 我知道这一点。但是,如果我创建一个发布版本,它运行时不会出现错误,并且菜单会正确显示。此外,我使用 Visual C++ 2010 中的菜单编辑器编辑了菜单,并保存了它 - 没有任何变化。因此,我排除了资源格式错误导致的菜单兼容性问题。

我在 ThinkPad T61p 上运行 Windows XP SP3。

创建菜单的代码是



    CMenu menu;
    menu.LoadMenu(RESOURCE_NAME);
    SetMenu(&menu);

并且在CFrameWnd的子类的上下文中运行。

我在谷歌上搜索了很多,并且相当肯定以前没有人遇到过这个问题;此外,我是所有 C++、MFC 和 Visual Studio 的新手。非常感谢您的帮助;如果我可以提供更多问题元数据,请告诉我,我会这样做。 提前致谢!

【问题讨论】:

LoadMenu() 有一个返回值。一个布尔值。它没有被检查,所以你当然不知道它为什么不能正常工作。 ASSERT 是一个调试结构,在 Release 中编译出来。如果您单击忽略,代码应该仍然像以前一样工作。 @graham.reeds,是的,除了由于调试弹出窗口而导致菜单不复存在的严重不便......我什至从未在调试模式下看到它。哦,我知道 ASSERT 是什么——问题是,它失败的事实可能应该告诉我出了点问题。我想知道如何解决这个问题。 @Hans Passant,菜单初始化后很久断言失败;第一次单击菜单时失败。一个 BOOL 只能告诉我应该是出了什么问题;当它在发布模式下工作。无论它给我 0 还是 1,我并没有真正获得那么多信息。但感谢您指出。 嗯,这就是他们使用断言的原因。你基本上得到了两个镜头,第一个来自函数返回值,另一个来自断言。然后当你构建 Release 版本时,他们耸耸肩说“他似乎不在乎,这一定不重要”。修复菜单。我们不能告诉你如何修复菜单,你什么也没说。 【参考方案1】:

根据 MSDN (http://msdn.microsoft.com/en-us/library/177ay1x0.aspx)

CMenu::LoadMenu() 需要传入一个参数,您的示例代码中缺少该参数。 请检查并确保您传递了有效的菜单资源 ID。

编辑:

您的菜单对象是在堆栈上构建的,一旦超出范围就会被销毁。 你从哪里调用你的 CWnd::SetMenu ?您需要确保对象的生命周期可以持续到下一个 CWnd::SetMenu 否则您将持有/引用一个悬空指针。

【讨论】:

感谢您的回答 - 虽然 is 正在传递,但我的“”已被过滤。我的失败。 您确定菜单实例必须继续存在吗?它的成员可以被 SetMenu 复制。 基于以下语句:“SetMenu 不会破坏先前的菜单。应用程序应调用 CMenu::DestroyMenu 成员函数来完成此任务。”我可以向你保证,他们不会复制它:) @Ryan:不,CMenu 对象必须存在。 SetMenu 不会复制它。 你当然是对的,我现在真的很傻。现在可以了,谢谢帮助!更具体地说:我将菜单变成了我的 Window 类的成员,并做了BOOL success=m_Menu.LoadMenu(IDR_MENU1); SetMenu(&m_Menu);

以上是关于在 Visual C++ 2005 中开发的 Visual C++ 项目 - 在 Visual C++ 2010 中,打开菜单时调试断言失败,但发布模式有效,如何解决?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 项目依赖问题 Visual Studio 2005

在安装时安装 Visual C++ Redistributables 2005

在 Visual Studio 2005 中创建 DLL

字符串比较在 Visual C++ 2005 中不起作用

在 Visual Studio 2005 C++ 中设置文件版本号

Visual Studio C++ 2005-2013 中的智能感知缺少函数定义