首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在线程中使用GetLastError

在线程中使用GetLastError
EN

Stack Overflow用户
提问于 2015-10-30 11:07:44
回答 1查看 654关注 0票数 1

不久前,我为Windows函数编写了一个简单的包装类。我编写了一组单元测试,以验证类产生的结果与对API的直接调用相匹配。

最近,我回到了添加有关在不同线程中使用包装类的单元测试。我发现了::GetLastError函数的一些问题。根据MSDN,函数应该保留每个线程的最后一个错误代码:

检索调用线程的最后一个错误代码值。最后一个错误代码是在每个线程基础上维护的.多个线程不会覆盖对方的上次错误代码。

我发现在某些情况下,最后一个错误代码实际上变为零。我成功地用以下简单的程序在单元测试之外复制了这个问题:

代码语言:javascript
复制
#include "stdafx.h"

#include <condition_variable>
#include <mutex>
#include <thread>
#include <Windows.h>

int main(int argc, char* argv[])
{
    ::DWORD setError1 = 123;
    ::DWORD setError2 = 456;

    // scenario 1 - show that main thread not polluted by sub-thread
    const auto act1 = [](::DWORD errorNo)
    {
        ::SetLastError(errorNo);
        const auto a = ::GetLastError(); // a = 123
    };

    ::SetLastError(setError2);
    const auto b = ::GetLastError(); // b = 456
    const auto c = ::GetLastError(); // c = 456
    std::thread sub1(act1, setError1);
    sub1.join();
    const auto d = ::GetLastError(); // d = 0 - WHY???


    // scenario 2 - show that sub thread not polluted by main thread
    std::condition_variable conditional;
    std::mutex mutex;
    bool flag = false;
    ::DWORD e;
    const auto act2 = [&mutex, &flag, &e, &conditional](::DWORD errorNo)
    {
        std::unique_lock<std::mutex> lock(mutex);
        ::SetLastError(errorNo);
        conditional.wait(lock, [&flag] { return flag; });
        e = ::GetLastError();  // e = 456 in Windows 8.1, 0 in Windows 10.0.10240.0 - WHY???
    };

    std::thread sub2(act2, setError2);
    {
        std::lock_guard<std::mutex> guard(mutex);
        ::SetLastError(setError1);
        flag = true;
    }
    conditional.notify_all();
    sub2.join();
    const auto f = ::GetLastError();  // f = 123;
    return 0;
}

我遇到的问题是de

  • 我发现主线程的最后一个错误代码在使用子线程时会看到重置为零。
  • 在使用Windows10SDK时,我发现子线程在等待std::condition_variable时会将最后一个错误重置为零。这并不是在使用Windows8.1SDK时重置的。

有人能帮我解释一下我看到的结果吗?这是Windows中的一个bug,还是微软C++实现中的一个bug?还是我自己的代码中的一个bug?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-30 11:13:09

很简单。下面是发生的事情:

  1. 你给SetLastError打电话。
  2. 您可以调用另一个函数,该函数依次调用SetLastError
  3. 调用GetLastError并获取最新值,该值是项2中设置的值,而不是项1中设置的值。

因此,看看您的代码,以及我的注释:

代码语言:javascript
复制
::SetLastError(setError2);          // item 1 from the list above
std::thread sub1(act1, setError1);  // item 2
sub1.join();                        // item 2
const auto d = ::GetLastError();    // item 3

还有你的另一个例子:

代码语言:javascript
复制
 ::SetLastError(errorNo);                          // item 1
 conditional.wait(lock, [&flag] { return flag; }); // item 2
 e = ::GetLastError();                             // item 3

在每一种情况下,我作为第2项注释的代码都调用API函数,然后调用SetLastError

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33434555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档