Windows XP 上的 ReadFile 函数失败,错误代码为 2

发布于 2024-10-27 10:47:09 字数 3112 浏览 0 评论 0原文

我的项目的一部分旨在循环中重新读取文件的某些部分(以指针移动到文件开头为前缀)。开始时,代码打开文件并正确写入“最小数据”,但进一步读取(在同一文件句柄上(!))失败,错误代码为 2(“找不到文件”)。

这里是与该过程相关的代码部分:

virtual-mem-buffer.h:

/**
 * Allocates and manages page-aligned virtual memory of the given amount
 */
class VirtualMemBuffer {
public:
    explicit VirtualMemBuffer(size_t size) { /* skipped */ };
/* skipped */
protected:
    void * data;
public:
    const void * buff() const { return this->data; };
};

header-file.h:

static const size_t cFileSize = 4096;

typedef std::map<std::wstring, HANDLE> handlers_conrainer_type;
typedef std::pair<std::wstring, bool> item_type;

class Config {
public:
    typedef std::vector<item_type > container_type;

    container_type files;
    /* skipped */
};

code-file.cpp(在某些函数内):

VirtualMemBuffer buffer(cFileSize);

Config config(...);
config->files.push_back(item_type(L"C:\\lock-file.lock", true));

/* skipped */

for (Config::container_type::const_iterator it = config->files.begin(); 
     it != config->files.end(); 
     ++it)
{
    HANDLE hFile = CreateFile(
        (LPCWSTR)(it->first.c_str()),
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (hFile == INVALID_HANDLE_VALUE) {
        DWORD error = GetLastError();
        // Could not open the file, ignore it
        continue;
    } else {
        DWORD bytes_written = 0;
        BOOL write_ok = WriteFile(
                                    hFile, 
                                    buffer.buff(), 
                                    cFileSize, 
                                    &bytes_written, 
                                    NULL);

        if (!write_ok || (bytes_written != (DWORD)(cFileSize))) {
            // Could not initialize the file, skip the file
            CloseHandle(hFile);
            continue;
        };

        handlers_container.insert(
                std::pair<std::wstring, HANDLE>(it->first, hFile)
                );
    };
};

/* skipped */

for (handlers_conrainer_type::const_iterator it = handlers_container.begin(); 
     it != handlers_container.end(); 
     ++it)
{
    DWORD bytes_read = 0;
    LARGE_INTEGER li;
        li.HighPart = 0;
        li.LowPart = 0;
    BOOL move_ok = SetFilePointerEx(it->second, li, NULL, FILE_BEGIN);
    BOOL read_ok = ReadFile(
                                it->second, 
                                buffer.buff(), 
                                cFileSize, 
                                &bytes_read, 
                                NULL);

    if (!read_ok || (bytes_read != cFileSize)) {
        DWORD error = GetLastError();        // error == 2 :-(
        /* skipped */
    };
};

如您所见,SetFilePointerEx()和ReadFile()都在相同的文件句柄。第一个(以及 CreateFile()、WriteFile() )从未失败,但 ReadFile() 从未成功。

有人观察到这种行为或者至少对此有任何线索吗?有什么问题以及如何修复(或避免)?

使用 MS Visual C++ 2008 Express Edition 在 Windows XP SP3 上编译的代码

感谢您的时间和建议!

I have a part of the project that is intended to re-read some portion of a file in a loop (prepended with the pointer movement to the beginning of the file). By start, the code opens the file and writes there the 'minimal data' correctly, but the further read (on the same file handle(!)) fails with error code 2 ('File not found').

Here the part of code related to the process:

virtual-mem-buffer.h:

/**
 * Allocates and manages page-aligned virtual memory of the given amount
 */
class VirtualMemBuffer {
public:
    explicit VirtualMemBuffer(size_t size) { /* skipped */ };
/* skipped */
protected:
    void * data;
public:
    const void * buff() const { return this->data; };
};

header-file.h:

static const size_t cFileSize = 4096;

typedef std::map<std::wstring, HANDLE> handlers_conrainer_type;
typedef std::pair<std::wstring, bool> item_type;

class Config {
public:
    typedef std::vector<item_type > container_type;

    container_type files;
    /* skipped */
};

code-file.cpp (inside some function):

VirtualMemBuffer buffer(cFileSize);

Config config(...);
config->files.push_back(item_type(L"C:\\lock-file.lock", true));

/* skipped */

for (Config::container_type::const_iterator it = config->files.begin(); 
     it != config->files.end(); 
     ++it)
{
    HANDLE hFile = CreateFile(
        (LPCWSTR)(it->first.c_str()),
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (hFile == INVALID_HANDLE_VALUE) {
        DWORD error = GetLastError();
        // Could not open the file, ignore it
        continue;
    } else {
        DWORD bytes_written = 0;
        BOOL write_ok = WriteFile(
                                    hFile, 
                                    buffer.buff(), 
                                    cFileSize, 
                                    &bytes_written, 
                                    NULL);

        if (!write_ok || (bytes_written != (DWORD)(cFileSize))) {
            // Could not initialize the file, skip the file
            CloseHandle(hFile);
            continue;
        };

        handlers_container.insert(
                std::pair<std::wstring, HANDLE>(it->first, hFile)
                );
    };
};

/* skipped */

for (handlers_conrainer_type::const_iterator it = handlers_container.begin(); 
     it != handlers_container.end(); 
     ++it)
{
    DWORD bytes_read = 0;
    LARGE_INTEGER li;
        li.HighPart = 0;
        li.LowPart = 0;
    BOOL move_ok = SetFilePointerEx(it->second, li, NULL, FILE_BEGIN);
    BOOL read_ok = ReadFile(
                                it->second, 
                                buffer.buff(), 
                                cFileSize, 
                                &bytes_read, 
                                NULL);

    if (!read_ok || (bytes_read != cFileSize)) {
        DWORD error = GetLastError();        // error == 2 :-(
        /* skipped */
    };
};

As you can see, SetFilePointerEx() and ReadFile() both operate on the same file handle. The first one (and CreateFile(), WriteFile() ) never failed, but ReadFile() never succeded.

Did anybody observe such a behavior or at least have any clue on this? What is wrong and how can it be fixed (or avoided)?

The code compiled on Windows XP SP3 using MS Visual C++ 2008 Express Edition

Thank you for your time and advices!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

三生池水覆流年 2024-11-03 10:47:10

在尝试读取之前,尝试使用 FlushFileBuffers(handle) 将写入提交到磁盘

Try FlushFileBuffers(handle) to commit the writes to disk before you try and read them

荒人说梦 2024-11-03 10:47:09

我找到了问题的根源 - ReadFile() 失败的错误代码在 MS VC++ 调试器中进行了测试,其中(以及何时)变量实际上超出了(块)范围,因此充满了垃圾。值 2 只是编译器针对这种情况的偏好。

我刚刚注意到这一点,并添加了一些进一步的错误检查和代码,发现真正的错误代码是 998(“对内存位置的访问无效”),它本身来自 VirtualMemBuffer 类,其中使用 PAGE_READONLY 标志调用 VirtualAlloc() :-(。

所以,这是我的错,抱歉。

感谢所有花时间帮助我解决这个问题的人。

I have found the root of the problem - the error code for the ReadFile() fail was tested in MS VC++ debugger where (and when) the variable was actually out of the (block) scope and thus flooded with garbage. The value 2 was just a compiler preference for such condition.

I have just noticed that and added some further error checking and code around that, and found that the real error code is 998 ('Invalid access to memory location') which itself came from the VirtualMemBuffer class where VirtualAlloc() was called with PAGE_READONLY flag :-(.

So, it was my fault, sorry.

Thanks to everyone who spent time trying to help me with this problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文