我如何安全地将变量的值传递给C ++方法,该方法仅将void *作为参数?

问题描述 投票:0回答:2

我有一个函数,将void*作为唯一参数,并且还返回void*gpioThreadFunc_t

我现在有一个类型为track_t的变量,它基本上是一个unsigned char,并且想用其值(!)作为参数来调用我的方法。反过来,该方法必须确保该参数确实是track_t(分别是unsigned char)并使用它。

我试图这样调用方法:

start_thread (Loop, (void *) &track);

…,其中Loop是方法的名称,track是有问题的(本地)变量。将其值设置为2时,该方法获得0或131或其他值,但不是2。

Loop的定义如下:

void *Loop (void *params);

有人知道如何调用我的方法并安全地传递必要的参数吗?还是应该忘记传递参数,而要依赖全局(或实例)变量?谢谢。

Clarification:我仍在处理我的代码,因此这不是调试请求。我问这个问题只是为了避免陷入陷阱。

c++ methods parameter-passing void-pointers
2个回答
2
投票

除非线程实际上需要访问track变量本身(以对其进行更改),否则您应该只传递track变量的value而不是其addressunsigned charvalue容易适合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();

2
投票

有人知道我如何调用我的方法并传递必要的参数

我试图这样调用方法:

start_thread (Loop, (void *) &track);

[您尝试过的工作,假设Loop将void指针转换回track_t*,并假设所指向的track对象保持活动状态,直到不再使用为止。

尽管在您的示例中,强制转换为void*是不必要的,因为所有对象指针都隐式转换为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(&params, &track, sizeof track);
start_thread (Loop, params);

// in Loop
track_t track;
std::memcpy(&track, &params, sizeof track); 

此优化还提高了安全性,因为不再存在任何间接调用,因此,在使用它之前,您再也不能不使指向性参数保持活动状态。

我将把它作为结合这些方法的练习。


0
投票

除了雷米·勒博的答案:

安全吗?

创建一个类,将void* Loop(void* params)设置为其私有静态成员,添加一个调用start_thread(Loop, reinterpret_cast<void*>(static_cast<uintptr_t>(track)))的公共静态成员(或朋友函数)。>

然后,您可以保证在编译时仅将[​​C0]作为参数调用Loop()

© www.soinside.com 2019 - 2024. All rights reserved.