第二次调用GetOpenFileName在Win 8.1 64位计算机上崩溃而没有错误

时间:2016-02-12 16:02:08

标签: c windows 32bit-64bit

我正在进行的个人项目是使用tinyfiledialogs来帮助处理一些跨平台的gui内容;这对于我测试过的Unix系统非常有用,但是当我在Windows 8.1 64位机器上进行测试时,我遇到了问题。

GetOpenFileName()函数从tinyfiledialogs.c调用时,或从下面的代码调用,将在第一次调用时正确执行,但在第二次调用对话窗口后不久就会崩溃。但是,这个似乎发生在我的64位计算机上 - 在Windows 7 32位计算机上运行以下代码(或我使用tinyfiledialogs.c的代码)可以正常运行。

#include <stdio.h>
#include <windows.h>

void openD(){

char Filestring[1024] = "\0";
OPENFILENAME ofn={0};

ofn.lStructSize = sizeof(OPENFILENAME);
ofn.lpstrFile = Filestring;
ofn.nMaxFile = 1024;
ofn.Flags = OFN_EXPLORER | OFN_ALLOWMULTISELECT;

int retval = GetOpenFileName(&ofn);
if(retval == 1) printf("True!\n");
else {
    printf("value: %d\n", retval);
    int err_val = CommDlgExtendedError();
    switch(err_val){
        case CDERR_DIALOGFAILURE:   printf("ERR: CDERR_DIALOGFAILURE\n");   break;
        case CDERR_FINDRESFAILURE:  printf("CDERR_FINDRESFAILURE\n");       break;
        case CDERR_INITIALIZATION:  printf("CDERR_INITIALIZATION\n");       break;
        case CDERR_LOADRESFAILURE:  printf("CDERR_LOADRESFAILURE\n");       break;
        case CDERR_LOADSTRFAILURE:  printf("CDERR_LOADSTRFAILURE\n");       break;
        case CDERR_LOCKRESFAILURE:  printf("CDERR_LOCKRESFAILURE\n");       break;
        case CDERR_MEMALLOCFAILURE: printf("CDERR_MEMALLOCFAILURE\n");      break;
        case CDERR_MEMLOCKFAILURE:  printf("CDERR_MEMLOCKFAILURE\n");       break;
        case CDERR_NOHINSTANCE:     printf("CDERR_NOHINSTANCE\n");          break;
        case CDERR_NOHOOK:          printf("CDERR_NOHOOK\n");               break;
        case CDERR_NOTEMPLATE:      printf("CDERR_NOTEMPLATE\n");           break;
        case CDERR_STRUCTSIZE:      printf("CDERR_STRUCTSIZE\n");           break;
        case FNERR_BUFFERTOOSMALL:  printf("FNERR_BUFFERTOOSMALL\n");       break;
        case FNERR_INVALIDFILENAME: printf("FNERR_INVALIDFILENAME\n");      break;
        case FNERR_SUBCLASSFAILURE: printf("FNERR_SUBCLASSFAILURE\n");      break;
    }
}
}

int main()
{
openD();
openD();
}

第一个调用返回TRUE,第二个调用无法返回,程序崩溃。使用VS Express 2012 Debugger附加到程序的运行实例时,在第二次调用时捕获以下异常;首先是一个弹出窗口:

Unhandled exception at 0x759C36DC (shell32.dll) in ofd_64.exe: 0xC0000005: Access violation reading location 0x70017AD8.

关注输出:

First-chance exception at 0x759C36DC (shell32.dll) in ofd_64.exe: 0xC0000005: Access violation reading location 0x70017AD8. Unhandled exception at 0x759C36DC (shell32.dll) in ofd_64.exe: 0xC0000005: Access violation reading location 0x70017AD8.

在Windows 8.1计算机上进行多次试验时,例外情况保持不变。

奇怪的是,如果我删除了OFN_EXPLORER标志,那么两个调用的进程都会正常执行。但这不是一个好的解决方案。任何帮助将不胜感激。

编辑:

来自VS Express 2012的调用堆栈显示:

shell32.dll!00007ffe6ef02777()  Unknown
shell32.dll!00007ffe6ebbf1c4()  Unknown
shell32.dll!00007ffe6ea5b5f3()  Unknown
shell32.dll!00007ffe6ea5b555()  Unknown
shell32.dll!00007ffe6ea5b493()  Unknown
shell32.dll!00007ffe6ea5b386()  Unknown
shell32.dll!00007ffe6eb07f02()  Unknown
shell32.dll!00007ffe6eb86d78()  Unknown
shell32.dll!00007ffe6e93bf9b()  Unknown
ExplorerFrame.dll!00007ffe5b912b30()    Unknown
ExplorerFrame.dll!00007ffe5b912abd()    Unknown
ExplorerFrame.dll!00007ffe5b8ff511()    Unknown
shell32.dll!00007ffe6e8043ed()  Unknown
shell32.dll!00007ffe6e813e1f()  Unknown
SHCore.dll!00007ffe6c30142f()   Unknown
ntdll.dll!00007ffe71bab247()    Unknown
ntdll.dll!00007ffe71bc8e15()    Unknown
kernel32.dll!00007ffe706b13d2() Unknown
ntdll.dll!00007ffe71ba54e4()    Unknown

2 个答案:

答案 0 :(得分:1)

As suggested to me elsewhere, I tried calling CoInitializeEx prior to the openD function calls - this has solved the problem, though I can't say why. It doesn't seem to matter whether I use the COINIT_APARTMENTTHREADED or COINIT_MULTITHREADED flag, either works. Perhaps it's just some oddity in my particular machine.

答案 1 :(得分:0)

这是堆栈大小的问题。不要覆盖VC ++ 32位属性->链接器->系统->堆栈保留大小中的默认堆栈大小。让它为空。因此问题在64位系统上得以解决。