【问题标题】:GetOpenFileName never returns when compiled in debug mode (VS2010)GetOpenFileName 在调试模式下编译时永远不会返回(VS2010)
【发布时间】:2011-11-10 12:34:10
【问题描述】:

当我在调试模式下编译我的程序时,GetOpenFileName(&ofn) 永远不会返回。

它在发布模式下工作得很好。我能发现的唯一区别是很多东西都在发布模式下被优化掉了。

OPENFILENAME ofn;
TCHAR szFile[MAX_PATH];

szFile[0] = '\0';
szFile[1] = '\0';

//Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = TEXT("Images (*.jpg;*.png;*.bmp;*.tga;*.psd)\0*.jpg;*.png;*.bmp;*.tga;*.psd\0\0");
ofn.lpstrInitialDir = TEXT(".");
ofn.lpstrTitle = TEXT("Open 512x512 image");
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
...
GetOpenFileName(&ofn)

我正在使用 Unicode 字符集进行编译。

如果我从ofn.lpstrFilter 的中间删除\0,它将在调试模式下工作,但显然过滤器无法正常工作。

这是\0点周围的调试和释放模式下字符串在内存中的样子:

...snip...
0x00364BB4  70 00  p.
0x00364BB6  73 00  s.
0x00364BB8  64 00  d.
0x00364BBA  29 00  ).
0x00364BBC  00 00  ..
0x00364BBE  2e 00  ..
0x00364BC0  6a 00  j.
0x00364BC2  70 00  p.
0x00364BC4  67 00  g.
0x00364BC6  3b 00  ;.
...snip...

我可能在做一些愚蠢的事情(我没有太多的 winapi /w Unicode 经验),但我不知道是什么。有什么想法吗?

编辑:使用当前代码更新。

基本上

ofn.lpstrFilter = TEXT("Images (*.jpg;*.png;*.bmp;*.tga;*.psd)*.jpg;*.png;*.bmp;*.tga;*.psd\0");
                                                              ^

有效,但是

ofn.lpstrFilter = TEXT("Images (*.jpg;*.png;*.bmp;*.tga;*.psd)\0*.jpg;*.png;*.bmp;*.tga;*.psd\0");
                                                              ^

没有。

编辑:尝试在新的 Visual Studio 项目中重现相同的错误,但我做不到。有用。对项目设置进行了比较,没有任何市长差异。

【问题讨论】:

  • 当您说“GetOpenFileName 永不返回”时,您的意思是对话框出现并正常运行,但是当您单击“确定”或“取消”时会锁定。或者,对话框根本没有出现?
  • @cbranch,它根本没有出现。它似乎处于无限循环中,但由于我没有调试数据,所以我留下了反汇编的数据。没有试图弄清楚它发生了什么,因为它有点痛苦。我很确定由于某种原因它无法解析过滤器,而只是进入一个循环尝试解析它。但我不知道为什么。
  • 我们是否可以假设您没有对 ofn 进行其他初始化,但您在发布的代码中显示了这一点?
  • 如果您的过滤器有问题,它不会向我跳出来。最后你有一个额外的(冗余)空终止符,但这没关系。这是编译成 .exe 还是 .dll?您使用的是哪个版本的 Windows?
  • 如果将 lpstrInitialDir 设置为 NULL 会发生什么?我不认为我曾经使用过这样的相对路径。我使用 NULL 或完整路径。

标签: c visual-studio-2010 winapi getopenfilename visual-leak-detector


【解决方案1】:

1 ofn.lpstrFilter 应以 两个 零结尾:\0\0

2 你确定ZeroMemory() 真的将ofn 的内容归零。你可以试试SecureZeroMemory()

引用2个note from msdn

当您想确保您的数据将被迅速覆盖时,请使用此 [SecureZeroMemory()] 函数而不是 ZeroMemory,因为某些 C++ 编译器可以通过完全删除来优化对 ZeroMemory 的调用。

我会简单地使用memset()

【讨论】:

  • 第二个应该由编译器自动附加。即使在末尾手动添加 2 个空字符也不能解决问题。
  • 是的,我打算用memset()重写它,它部分是从使用ZeroMemory()的文档中复制粘贴代码
【解决方案2】:

一些事情......

1) 您正在初始化lpstrFile 两次。

ofn.lpstrFile = szFile;
ofn.lpstrFile = TEXT('\0');

2)你应该初始化szFile(可能是你在#1中的意图):

TCHAR szFile[MAX_PATH];
szFile[0] = '\0';

3) nMaxFile 应该是最大字符数,而不是字节数。所以,你想要MAX_PATHsizeof(szFile) / sizeof(TCHAR).

4) 您的文件过滤器中缺少一个“*”:应该是 *.jpg

【讨论】:

  • 不错,但不能解决问题。这可能是在我试图让这个东西工作时引入的:
  • 是的,从一开始就完全没有注意到#3,但仍然没有。如果我从过滤器中间删除空字符,即使使用稍微不正确的代码也可以在发布和调试中工作。所以这有点棘手。
【解决方案3】:

我终于隔离了构建之间的唯一区别:

我在调试版本中使用了Visual Leak Detector。删除后,它开始工作了。

我会尽力查明为什么会发生这种情况,但我只是想感谢每一位试图帮助我的人。我希望我能奖励更多积分。

更多人有类似问题:

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-15
  • 2017-12-06
  • 2017-07-26
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
相关资源
最近更新 更多