pthread_制造混乱

pthread_create confusion

本文关键字:混乱 制造 pthread      更新时间:2023-10-16

在很多情况下,我都看到过这种情况

class Foo
{
static void* ThreadFun(void* p)
{
Derived* args = (Derived*)p;
//do something with args.
//example 
//cout << args->getname();
}
void function()
{
Base* args = new Derived();
args->setname("test");
pthread_t id;
int ret = pthread_create(&id, NULL, ThreadFun, (void*) args);    
}
}

首先,这是正确的C++代码吗?还是我错过了什么?我已经做了一些阅读,很明显,将类的指针投射到void会导致信息丢失,并且在派生类上调用getname()可能是非法的。

如果我理解正确,他们的建议是这样的:

void function()
{
Base* args = new Derived();
args->setname("test");
void* pargs = (Base*)malloc(sizeof(*args)); // to be freed in ThreadFun
pargs = args;
pthread_t id;
int ret = pthread_create(&id, NULL, ThreadFun, pargs );    
}

我真的不明白,我该怎么做?

哦,哇。。。不,你的第二个例子泄露了malloc()分配的内存,从注释中可以看出,如果你遵循这个建议,当你认为你正在释放malloc)分配时,你将在ThreadFun中释放new Derived()分配。

关于将指向类的指针强制转换为void*导致信息丢失。。。。事实并非如此。平原&易于理解的它失去的是编译器对指针含义的理解。如果知道它的意思,你总是可以把它转换回正确的类型&恢复其全部功能,这正是第一个示例所做的。当ThreadFun()函数在新线程中启动时,它将void*强制转换回其原始类型Derived*。

我注意到,当您最初调用new Derived()分配时,您将返回指针分配给了Base*类型的指针。我假设class Derived继承自class Base,所以那里的赋值实际上会导致"信息丢失",因为它是类型为Base*的指针,但会丢失Derived类的任何非多态行为。但是,当您在ThreadFun()中将其转换回真实类型时,它将恢复其全部功能。请注意,如果您分配了一个new Base对象并用它启动新线程,并且在ThreadFun()中将其强制转换为Derived*,编译器会允许您这样做,但您会有未定义的行为。。。可能是车祸。因为(由于pthreads接口)您必须通过一个void*,所以即使使用C++样式的强制转换,也没有类型检查的安全性。因此,您可以将void*转换为您想要的任何内容,编译器会允许您这样做。当然,唯一真正有效的类型转换是(Base*)(Derived*),或者继承层次结构中介于它们之间的任何类型。

我还应该提到,作为一个void*,您不能删除对象并运行其析构函数。要删除对象,您需要将指针强制转换回它的任何类型,以便编译器知道要调用什么析构函数。对于类型为Base*Derived类的指针,您可能会遇到另一种棘手的棘手情况。。。。如果Base::~Base()析构函数不是virtual,如果通过在Base*上调用delete来删除Derived对象,则分配将被完全解除分配,但只有对象的Base部分将运行其析构函数。。。。。除非析构函数是用virtual关键字定义的,否则即使只有Base*,也可以删除Derived对象?