如何安全地将变量的值传递给 C++ 方法,该方法只会将 void* 作为参数?
How can I safely pass a value of a variable to a C++ method, which would only take a void* as an argument?
我有一个函数将 void*
作为唯一参数,并返回 void*
:gpioThreadFunc_t
我现在有一个 track_t 类型的变量,它基本上是一个 unsigned char
,我想用它的值 (!) 作为参数调用我的方法。反过来,该方法必须确保参数确实是 track_t
(resp. unsigned char
)并使用它。
我试过这样调用方法:
start_thread (Loop, (void *) &track);
…其中 Loop
是方法的名称,track
是相关的(局部)变量。将其值设置为 2 时,该方法得到的是 0 或 131 或其他值,但不是 2。
Loop
定义如下:
void *Loop (void *params);
有人知道我如何调用我的方法并安全地传递必要的参数吗?或者我应该忘记参数传递并改为依赖全局(或实例)变量?谢谢。
澄清:我仍在编写我的代码,因此这不是调试请求。我问这个问题只是为了不 运行 掉入陷阱。
Does anybody know how I can call my method and pass the necessary argument
I tried to call the method like this:
start_thread (Loop, (void *) &track);
假设 Loop
将 void 指针转换回 track_t*
并假设指向的 track
对象在不再使用之前保持活动状态,您尝试的方法将起作用。
虽然在您的示例中强制转换为 void*
是不必要的,因为所有对象指针都隐式转换为 void*
.
How can I safely pass a ... void*
无法使接受 void*
的函数安全。它本质上是类型不安全的。
您可以做的是编写一个类型安全的包装器模板,这样就不必直接调用 start_thread
。示例:
template<class T>
using fun_t = T*(T*);
template<auto fun_ptr, class T>
void start_thread_safer(T* params)
{
auto callback = [](void* vparams) -> void* {
return fun_ptr(static_cast<T*>(vparams));
};
start_thread(callback, params);
}
现在您可以安全地使用:
track_t* Loop (track_t* params);
start_thread_safer<Loop>(&track);
有一种优化可以避免间接寻址:由于 unsigned char
保证适合 void*
的内存,您可以直接传递该内存中的对象。对于整数(例如 unsigned char
),这很简单:
str::uintptr_t temp = track;
start_thread (Loop, reinterpret_cast<void*>(temp));
// in Loop
track_t track = reinterpret_cast<str::uintptr_t>(params);
如果传递的类型不是整数,但可以简单地复制并适合指针,则以下也适用:
void* params = nullptr;
static_assert(sizeof params >= sizeof track);
std::memcpy(¶ms, &track, sizeof track);
start_thread (Loop, params);
// in Loop
track_t track;
std::memcpy(&track, ¶ms, sizeof track);
此优化还提高了安全性,因为不再有任何间接寻址,因此您不会再无法保持指向的参数处于活动状态直到它被使用。
我将把它作为结合这些方法的练习。
除非线程实际上需要访问 track
变量本身(对其进行更改),否则您应该只传递 value 的 [=12] =] 变量而不是其 地址 。 unsigned char
的 value 很容易放入 void*
指针的位中:
void* Loop(void *params) {
track_t track = static_cast<track_t>(reinterpret_cast<uintptr_t>(params));
...
}
...
track_t track = 2;
start_thread(Loop, reinterpret_cast<void*>(static_cast<uintptr_t>(track)));
否则,你可以动态分配一个track_t
传给线程,然后在线程退出前释放它:
void* Loop(void *params) {
std::unique_ptr<track_t> track(static_cast<track_t*>(params));
...
}
...
std::unique_ptr<track_t> track(new track_t(2));
if (start_thread(Loop, track.get()))
track.release();
我有一个函数将 void*
作为唯一参数,并返回 void*
:gpioThreadFunc_t
我现在有一个 track_t 类型的变量,它基本上是一个 unsigned char
,我想用它的值 (!) 作为参数调用我的方法。反过来,该方法必须确保参数确实是 track_t
(resp. unsigned char
)并使用它。
我试过这样调用方法:
start_thread (Loop, (void *) &track);
…其中 Loop
是方法的名称,track
是相关的(局部)变量。将其值设置为 2 时,该方法得到的是 0 或 131 或其他值,但不是 2。
Loop
定义如下:
void *Loop (void *params);
有人知道我如何调用我的方法并安全地传递必要的参数吗?或者我应该忘记参数传递并改为依赖全局(或实例)变量?谢谢。
澄清:我仍在编写我的代码,因此这不是调试请求。我问这个问题只是为了不 运行 掉入陷阱。
Does anybody know how I can call my method and pass the necessary argument
I tried to call the method like this:
start_thread (Loop, (void *) &track);
假设 Loop
将 void 指针转换回 track_t*
并假设指向的 track
对象在不再使用之前保持活动状态,您尝试的方法将起作用。
虽然在您的示例中强制转换为 void*
是不必要的,因为所有对象指针都隐式转换为 void*
.
How can I safely pass a ... void*
无法使接受 void*
的函数安全。它本质上是类型不安全的。
您可以做的是编写一个类型安全的包装器模板,这样就不必直接调用 start_thread
。示例:
template<class T>
using fun_t = T*(T*);
template<auto fun_ptr, class T>
void start_thread_safer(T* params)
{
auto callback = [](void* vparams) -> void* {
return fun_ptr(static_cast<T*>(vparams));
};
start_thread(callback, params);
}
现在您可以安全地使用:
track_t* Loop (track_t* params);
start_thread_safer<Loop>(&track);
有一种优化可以避免间接寻址:由于 unsigned char
保证适合 void*
的内存,您可以直接传递该内存中的对象。对于整数(例如 unsigned char
),这很简单:
str::uintptr_t temp = track;
start_thread (Loop, reinterpret_cast<void*>(temp));
// in Loop
track_t track = reinterpret_cast<str::uintptr_t>(params);
如果传递的类型不是整数,但可以简单地复制并适合指针,则以下也适用:
void* params = nullptr;
static_assert(sizeof params >= sizeof track);
std::memcpy(¶ms, &track, sizeof track);
start_thread (Loop, params);
// in Loop
track_t track;
std::memcpy(&track, ¶ms, sizeof track);
此优化还提高了安全性,因为不再有任何间接寻址,因此您不会再无法保持指向的参数处于活动状态直到它被使用。
我将把它作为结合这些方法的练习。
除非线程实际上需要访问 track
变量本身(对其进行更改),否则您应该只传递 value 的 [=12] =] 变量而不是其 地址 。 unsigned char
的 value 很容易放入 void*
指针的位中:
void* Loop(void *params) {
track_t track = static_cast<track_t>(reinterpret_cast<uintptr_t>(params));
...
}
...
track_t track = 2;
start_thread(Loop, reinterpret_cast<void*>(static_cast<uintptr_t>(track)));
否则,你可以动态分配一个track_t
传给线程,然后在线程退出前释放它:
void* Loop(void *params) {
std::unique_ptr<track_t> track(static_cast<track_t*>(params));
...
}
...
std::unique_ptr<track_t> track(new track_t(2));
if (start_thread(Loop, track.get()))
track.release();