调用函数FindNextFile抛出访问冲突异常

时间:2013-07-05 07:24:24

标签: c winapi access-violation unhandled-exception

我使用Win32 API编写一个c程序FindNextFile来查找文件

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

int _tmain(int argc, TCHAR *argv[])
{
    HANDLE hNextFile;
    WIN32_FIND_DATA findFileData;
    LPCTSTR fileName = argv[1]; //input argument "C:\test\file*.txt"

    hNextFile = FindFirstFile(fileName, &findFileData);

    while(hNextFile != INVALID_HANDLE_VALUE)
    {
        printf("long name: %s\t8dot3 name: %s\n", findFileData.cFileName, findFileData.cAlternateFileName);
        hNextFile = FindNextFile(fileName, &findFileData); //Unhandled exception here!
    }
    printf("%s", GetLastError());
    return 0;
}

首先调用FindNextFile时会抛出异常。 例外信息:

  

findfile.exe中0x77178dc9处的未处理异常:0xC0000005:Access   违规写入位置0x005c0080。

你能给我一些建议吗?

提前致谢。


我修改了这样的代码,它运行正常。感谢皮埃尔的解释。

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

int _tmain(int argc, TCHAR *argv[])
{
    HANDLE hNextFind;
    WIN32_FIND_DATA findFileData;
    LPCTSTR fileName = argv[1];
    BOOL result = TRUE;

    if((hNextFind = FindFirstFile(fileName, &findFileData)) == INVALID_HANDLE_VALUE)
        return 1;

    while(result)
    {
        _tprintf(TEXT("long name: %s\t8dot3 name: %s\n"), findFileData.cFileName, findFileData.cAlternateFileName);
        result = FindNextFile(hNextFind, &findFileData);
    }
    FindClose(hNextFind);
    return 0;
}

3 个答案:

答案 0 :(得分:1)

您的代码中有很多错误。

  • 首先,您没有正确使用FindNextFile,原型:

    BOOL WINAPI FindNextFile(
      _In_   HANDLE hFindFile,
      _Out_  LPWIN32_FIND_DATA lpFindFileData
    );
    
  • 之后,您没有正确使用GetLastError(),他们会触发异常。 GetLastError返回DWORD,您可以将其打印为字符串。 (http://msdn.microsoft.com/en-us/library/ms679360(v=vs.85).aspx

以下是您的代码应该是什么样子的示例:

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

int _tmain(int argc, TCHAR *argv[])
{
    HANDLE hNextFile;
    WIN32_FIND_DATA findFileData;
    LPCTSTR fileName = argv[1]; //input argument "C:\test\file*.txt"

    hNextFile = FindFirstFile(fileName, &findFileData);
    BOOL res = TRUE;
  //^^^^^^^^^^^^^^^^

    while(hNextFile != INVALID_HANDLE_VALUE && res)
    //                                      ^^^^^^
    {
        printf("long name: %s\t8dot3 name: %s\n", findFileData.cFileName, findFileData.cAlternateFileName);
        res = FindNextFile(hNextFile, &findFileData); //Unhandled exception here!
      //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    }
    printf("%d", GetLastError());
    //      ^^  // You can also use FormatMessage as it is said in the documentation
    return 0;
}

答案 1 :(得分:0)

FindNextFile返回TRUE或FALSE,它不返回HANDLE。您从FindFirstFile获得的原始句柄仍然有效,直到您将其传递给FindClose

hNextFile = FindFirstFile(fileName, &findFileData);
if(hNextFile != INVALID_HANDLE_VALUE)
{
    do
    {
        printf("long name: %s\t8dot3 name: %s\n", findFileData.cFileName, findFileData.cAlternateFileName);
    } while (FindNextFile(fileName, &findFileData));
    FindClose(hNextFile);
}

答案 2 :(得分:0)

您的代码中存在一些问题。

您的原始代码为:

hNextFile = FindNextFile(fileName, &findFileData);

但是如果你查看prototype of FindNextFile(),你会发现:

BOOL WINAPI FindNextFile(
  _In_   HANDLE hFindFile,
  _Out_  LPWIN32_FIND_DATA lpFindFileData
);

因此,该函数返回BOOL,第一个参数是HANDLE,这不是代码中的内容。

此外,你有:

printf("long name: %s\t8dot3 name: %s\n", findFileData.cFileName,
       findFileData.cAlternateFileName);

但这与您在代码的其他部分中使用的TCHAR模型不一致 为了保持连贯,您应该使用_tprintf()代替printf(),并使用_T("...")TEXT("...")修饰字符串:

// Use _tprintf() and _T("...") for coherence with TCHAR model
_tprintf(_T("long name: %s\t8dot3 name: %s\n"), 
         findFileData.cFileName, findFileData.cAlternateFileName);

此外,你有:

printf("%s", GetLastError());

GetLastError()返回DWORD,这是一个无符号的32位整数 但是在printf()格式字符串中使用了%s,它是原始C字符串的占位符。
相反,您可能希望使用%u格式说明符(并使用_tprintf()TCHAR模型保持一致):

_tprintf(_T("Last error code: %u\n"), GetLastError());

请注意,MSDN在Listing the Files in a Directory上有一个示例。