- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在调试一个使用 std::thread
的多线程应用程序。运行一个函数。调试时我达到以下代码。
extern "C" uintptr_t __cdecl _beginthreadex(
void* const security_descriptor,
unsigned int const stack_size,
_beginthreadex_proc_type const procedure,
void* const context,
unsigned int const creation_flags,
unsigned int* const thread_id_result
)
{
_VALIDATE_RETURN(procedure != nullptr, EINVAL, 0);
unique_thread_parameter parameter(create_thread_parameter(procedure, context));
if (!parameter)
{
return 0;
}
DWORD thread_id;
HANDLE const thread_handle = CreateThread(
reinterpret_cast<LPSECURITY_ATTRIBUTES>(security_descriptor),
stack_size,
thread_start<_beginthreadex_proc_type, true>,
parameter.get(),
creation_flags,
&thread_id);
if (!thread_handle)
{
__acrt_errno_map_os_error(GetLastError());
return 0;
}
if (thread_id_result)
{
*thread_id_result = thread_id;
}
// If we successfully created the thread, the thread now owns its parameter:
parameter.detach();
return reinterpret_cast<uintptr_t>(thread_handle);
}
但我无法理解函数的地址是如何传递给
CreateThread
的。 API。为什么使用
thread_start<_beginthreadex_proc_type, true>
,以及如何通过该语句计算函数的地址以便由线程运行?
最佳答案
显示的代码( _beginthreadex
函数)是 VC++ CRT 的一部分(可以在例如C:\Program Files (x86)\Windows Kits\10\Source\10.0.17763.0\ucrt\startup\thread.cpp
)。unique_thread_parameter
的一个实例是一个持有线程 procedure
的结构指针,context
参数、线程和模块 HANDLE
年代:
// corecrt_internal.h
typedef struct __acrt_thread_parameter
{
// The thread procedure and context argument
void* _procedure;
void* _context;
// The handle for the newly created thread. This is initialized only from
// _beginthread (not _beginthreadex). When a thread created via _beginthread
// exits, it frees this handle.
HANDLE _thread_handle;
// The handle for the module in which the user's thread procedure is defined.
// This may be null if the handle could not be obtained. This handle enables
// us to bump the reference count of the user's module, to ensure that the
// module will not be unloaded while the thread is executing. When the thread
// exits, it frees this handle.
HMODULE _module_handle;
// This flag is true if RoInitialized was called on the thread to initialize
// it into the MTA.
bool _initialized_apartment;
} __acrt_thread_parameter;
// thread.cpp
using unique_thread_parameter = __crt_unique_heap_ptr<
__acrt_thread_parameter,
thread_parameter_free_policy>;
create_thread_parameter
创建这样一个实例:
static __acrt_thread_parameter* __cdecl create_thread_parameter(
void* const procedure,
void* const context
) throw()
{
unique_thread_parameter parameter(_calloc_crt_t(__acrt_thread_parameter, 1).detach());
if (!parameter)
{
return nullptr;
}
parameter.get()->_procedure = procedure;
parameter.get()->_context = context;
// Attempt to bump the reference count of the module in which the user's
// thread procedure is defined, to ensure that the module will stay loaded
// as long as the thread is executing. We will release this HMDOULE when
// the thread procedure returns or _endthreadex is called.
GetModuleHandleExW(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
reinterpret_cast<LPCWSTR>(procedure),
¶meter.get()->_module_handle);
return parameter.detach();
}
thread_start
是调用线程过程的模板函数:
template <typename ThreadProcedure>
static unsigned long WINAPI thread_start(void* const parameter) throw()
{
if (!parameter)
{
ExitThread(GetLastError());
}
__acrt_thread_parameter* const context = static_cast<__acrt_thread_parameter*>(parameter);
__acrt_getptd()->_beginthread_context = context;
if (__acrt_get_begin_thread_init_policy() == begin_thread_init_policy_ro_initialize)
{
context->_initialized_apartment = __acrt_RoInitialize(RO_INIT_MULTITHREADED) == S_OK;
}
__try
{
ThreadProcedure const procedure = reinterpret_cast<ThreadProcedure>(context->_procedure);
_endthreadex(invoke_thread_procedure(procedure, context->_context));
}
__except (_seh_filter_exe(GetExceptionCode(), GetExceptionInformation()))
{
// Execution should never reach here:
_exit(GetExceptionCode());
}
// This return statement will never be reached. All execution paths result
// in the thread or process exiting.
return 0;
}
它本质上调用
invoke_thread_procedure
,它只是调用
procedure
, 传入
context
:
static __forceinline unsigned int invoke_thread_procedure(
_beginthreadex_proc_type const procedure,
void* const context
) throw()
{
return procedure(context);
}
调用周围的代码会做一些簿记以保持 CRT 的一致性,例如
_endthreadex
)。
关于c++ - 函数的地址如何传递给 std::thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63500919/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!