6

我有指向单例类的指针对象。

线程1:当前正在执行上述对象的一个​​成员函数。
线程2:当对象的成员函数还在被线程1执行时,删除上述对象。

执行成员函数的线程 1 会发生什么?是否会中途停止执行?

4

4 回答 4

4

除非您格外小心,否则这可能是未定义的行为。

在您的线程以无序(基本上是非同步)方式访问对象时删除对象是未定义的行为,即使您很幸运。

在与主线程中的删除同步之后访问对象的成员(不仅仅是运行成员:实际访问成员 - 调用成员函数,读取成员变量等)也是未定义的行为。

如果你小心地与主线程同步,那么在同步后不要访问成员数据,也不要调用不同的成员函数,并且主线程在同步后删除对象,那么你就完全可以了。

几乎没有任何东西会导致未定义的行为。

虽然未定义的行为几乎可以做任何事情,但由于对象被删除而导致成员函数中代码的执行突然停止,这将是意想不到的未定义行为。您更有可能遇到段错误、内存损坏等。更糟糕的是,在许多情况下,事情会“很好”。

于 2013-08-09T15:08:38.190 回答
2

您很可能会得到未定义的行为。线程 1 可能会出现 seg 错误,或者如果在删除对象后它不访问任何成员数据(并且不进行虚函数调用),它可能会继续愉快地运行。这也取决于删除后内存区域会发生什么。清除了吗?它是不可写/不可读的吗?在重用数据区域来处理其他分配方面,这一切都高度依赖于实现,也取决于应用程序的数据需求。

指导原则是在对象的所有使用完成之前永远不要删除它。在某些例外情况下,成员函数会删除它们所操作的对象,以确保在删除点之后不再有成员访问。但除了那些实际上证明删除成员的少数情况外,不要这样做。

在您所描述的多线程环境中,绝对确定将对象生命周期与对象使用相协调,否则您可能很难调试(平台相关和非确定性)行为。

于 2013-08-09T13:57:26.017 回答
0

简短的回答:你不应该这样做......你需要确保在删除之前没有使用该对象。

就 C++ 标准规定的内容而言,它(可能)是未定义的行为——很可能会发生意想不到的事情。其基础是在对象被销毁后使用对象的任何成员(函数或变量)是未定义的行为。当然,如果成员函数看起来像这样:

void foo::func()
{
   for(;;)
   {
     // do nothing here 
   }
}

那么它不是未定义的行为,并且线程可以无限期地运行,而不会产生任何不良影响,并且行为(我相信)是明确定义的(它只是继续运行)。

当然线程 1 的执行肯定不会仅仅因为对象被删除而停止。也就是说,除非对象实际上包含线程 1 的线程对象——在这种情况下,线程对象的析构函数可能会杀死线程。

在实践中,如果对象被删除,它的内存就会被释放,并且内存很可能会在一段时间后被其他对象重用。根据成员函数正在做什么,例如,它所指的对象的哪些部分,以及它如何使用这些成员,它可能会导致崩溃,或者如果它做了类似的事情x++;x成员变量在哪里),它会修改一些内存不再是它的所有者 - 这可能很难调试,因为它看起来像是在随机改变其他对象......这绝对不是很好(而且很可能,它只会在某些时候发生,使得当它出错时真的很难发现)。

这不可能有什么好结果。

必须确保该对象未以任何方式被使用才能删除它。一种方法当然是拥有线程 1 的线程对象,然后终止线程。

于 2013-08-09T14:08:07.727 回答
0

未定义的行为是正确的答案。为避免此类事情,请考虑使用智能指针,例如: http: //www.boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm或:http ://en.cppreference.com/w/ cpp/内存/shared_ptr。它们具有引用计数机制,不允许您使用对象进行删除。

于 2013-08-09T14:11:09.513 回答