Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Windows 10在我的程序中启动额外的线程? 使用VisualStudio 2015,在一个新的空C++项目中,为控制台应用程序生成以下内容: int main() { return 0; }_C++_Windows_Multithreading_Threadpool - Fatal编程技术网

为什么Windows 10在我的程序中启动额外的线程? 使用VisualStudio 2015,在一个新的空C++项目中,为控制台应用程序生成以下内容: int main() { return 0; }

为什么Windows 10在我的程序中启动额外的线程? 使用VisualStudio 2015,在一个新的空C++项目中,为控制台应用程序生成以下内容: int main() { return 0; },c++,windows,multithreading,threadpool,C++,Windows,Multithreading,Threadpool,在返回上设置断点,并在调试器中启动程序。在Windows 7上,截至断点,此程序只有一个线程。但在Windows10上,它有五个(!)线程:主线程和四个“工作线程”等待同步对象 谁在启动线程池(或者如何找到)?Crystal ball说调试>窗口>线程窗口在ntdll.dll中显示这些线程!TppWorkerThread。请确保使Microsoft Symbol服务器能够自己看到这一点,请使用工具>选项>调试>符号 这也发生在VS2013中,因此它肯定不是由新的VS2015诊断功能引起的,@Ad

在返回上设置断点,并在调试器中启动程序。在Windows 7上,截至断点,此程序只有一个线程。但在Windows10上,它有五个(!)线程:主线程和四个“工作线程”等待同步对象


谁在启动线程池(或者如何找到)?

Crystal ball说调试>窗口>线程窗口在
ntdll.dll中显示这些线程!TppWorkerThread
。请确保使Microsoft Symbol服务器能够自己看到这一点,请使用工具>选项>调试>符号

这也发生在VS2013中,因此它肯定不是由新的VS2015诊断功能引起的,@Adam的猜测不可能是正确的

TppWorkerThread()是线程池线程的入口点。当我在这个函数上用Debug>newbreakpoint>functionbreakpoint设置断点时。当第二个线程池线程开始执行时,我幸运地捕获了第一个线程池线程的堆栈跟踪:

    ntdll.dll!_NtOpenFile@24()  Unknown
    ntdll.dll!LdrpMapDllNtFileName()    Unknown
    ntdll.dll!LdrpMapDllSearchPath()    Unknown
    ntdll.dll!LdrpProcessWork() Unknown
    ntdll.dll!_LdrpWorkCallback@12()    Unknown
    ntdll.dll!TppWorkpExecuteCallback() Unknown
    ntdll.dll!TppWorkerThread() Unknown
    kernel32.dll!@BaseThreadInitThunk@12()  Unknown
    ntdll.dll!__RtlUserThreadStart()    Unknown
>   ntdll.dll!__RtlUserThreadStart@8()  Unknown
显然,加载程序正在使用Windows 10上的线程池加载DLL。这当然是新的:)在这一点上,主线程也在加载程序中执行,并发工作


因此,Windows 10利用多个内核来更快地初始化进程。这是一个特性,而不是bug:)

它是默认的线程池。


每个进程都有一个默认的线程池。

这也启发了我,所以我决定找到我个人的答案;正如另一张海报所说,它有点“水晶球”的可爱,但是

可能的原因是您的一个线程称为:

  • WaitForSingleObject或
  • WaitForMultipleObjects
在最新版本的Windows中实现这一点似乎产生了一个线程池,以方便等待对象(不知道为什么)

这也可能发生在main之前,因为您有一些代码导致创建全局作用域对象,然后在您到达入口点之前启动代码(这甚至可能在Windows 10 SDK的一些标准库代码中)

对于任何想找出自己具体原因的人,您可以尝试以下方法:

class RunBeforeMain
{
public:
    RunBeforeMain()
    {
        HMODULE hNtDll = (HMODULE)LoadLibrary(_T("ntdll.dll"));
        FARPROC lpNeeded = GetProcAddress(hNtDll,"NtWaitForMultipleObjects");
        DebugBreakPoint();
    }
};

RunBeforeMain go;

int CALLBACK WinMain(
  _In_ HINSTANCE hInstance,
  _In_ HINSTANCE hPrevInstance,
  _In_ LPSTR     lpCmdLine,
  _In_ int       nCmdShow
)
{
}
运行此操作时,您将获得LPREQUIRED中NtDll过程NtWaitForMultipleObjects的库加载位置,获取该地址并将其粘贴到“反汇编视图”窗口中,然后在第一行上放置断点

现在继续运行您的解决方案

有几点需要注意:

  • 我们无法有效地控制globals的初始化顺序,这就是为什么如果你有良好的编码意识,你会不惜一切代价避免它们(除非有例外需要)。由于这个事实,我们不能保证我们的全局将在任何其他全局导致额外线程之前触发
  • 虽然这是在main之前,但任何库的DLL加载都将继续进行我们的任何调用,因此,这可能已经太晚了(您可以使用诸如强制不自动加载库之类的黑客,但这远远超出了我在这里关心的意愿lol)

  • 希望这对某人有所帮助:)

    我知道这是一个有5年历史的问题,但Microsoft已经告诉您它使用“遥测”,您也已经知道Microsoft Visual Studio 2015及更高版本向您的可执行文件中注入了一些不允许编辑的额外代码。根据微软的说法,这些额外的代码不是你的事,你无法控制它,也不允许你看到它。你知道的。您选择使用VisualStudio,并且您知道Microsoft已经告诉您他们这样做了,您已经接受了后果。微软已经告诉过你它是这样做的。如果Microsoft注入的代码与您自己的代码冲突,那么不要期望您自己的代码具有优先权,可以按您的意愿运行。再说一遍,你已经知道这一点了

    这些额外线程来自Microsoft,而不是您,除非您选择使用Visual Studio 2015及更高版本

    没必要感到惊讶。微软已经公开告诉你了

    它[不是]等待您使用的线程池。微软已经告诉过你,他们在VisualStudio2015及以上版本中这样做

    Windows 10[没有]利用多核来更快地初始化进程。[它]在很大程度上是[微软遥测技术]的一项功能,而不是一个bug[而是实际上将微软注入的遥测代码注入到您的可执行文件中,而不受您的任何控制。]:[(]

    想要阻止它吗?其中一种方法是:在非遥测嵌入式操作系统上或在没有“遥测”功能的旧Microsoft操作系统上编写C++11程序;在不使用任何版本的Microsoft Visual Studio的情况下编译;使用此程序启动并快速对当前受Microsoft程序感染的线程进行子类化,然后停止子类程序启动的任何线程,然后将所有请求重定向到子类程序最初不打算使用的DLL


    Microsoft不是你的敌人,你选择做出然后忽略直到受伤的假设可能是你的敌人。

    关于Windows和无休止循环的笑话来了……可能进程在Windows 10上默认获得线程池。我首先在
    CreateThread
    上放置断点。请注意,按名称放置断点在Visual Studio调试器中使用windbg非常常见,但这是可能的,但需要学习一些不寻常的菜单命令。它是您在Visual Studio中观察到的trhads?还是您可以看到的线程(例如在中)当您直接从命令行运行代码时?@Christophe:您是否建议Visual Studio调试器将线程池注入正在测试的进程中,但仅在Windows 10上?我的问题是:假设我已经分析了我的服务器,我看到5个线程