我有单例类的指针对象。
线程1:当前正在执行上述对象的成员函数 线程2:当线程1仍在执行对象的成员函数时删除上述对象。
正在执行成员函数的线程1会发生什么?执行是否会在中途停止?
答案 0 :(得分:4)
这可能是未定义的行为,除非你格外小心。
当线程以无序(非同步,基本上)方式访问它时,删除对象是未定义的行为,即使你很幸运。
在从主线程中删除同步后,访问对象的成员(不仅仅是运行成员:实际访问成员 - 调用成员函数,读取成员变量等)也是未定义的行为。
如果你仔细地与主线程同步,那么在同步之后不要访问成员数据也不要调用不同的成员函数,主线程在同步后删除对象,然后你是完全可以。
几乎任何不足都会导致未定义的行为。
虽然未定义的行为几乎可以做任何事情,但是这会导致成员函数中的代码执行突然因为删除对象而导致意外的未定义行为。您更有可能遇到段错误,内存损坏等。更糟糕的是,在许多情况下,事情会“很好”。
答案 1 :(得分:2)
您很可能会得到未定义的行为。线程1可以获得seg错误,或者如果在删除对象后没有访问任何成员数据(并且不进行虚函数调用),它可以继续快速继续。它还取决于删除后内存区域发生了什么。它被清除了吗?它是不可写/不可读的吗?它依赖于高度依赖于实现的依赖于应用程序的数据需求,重用数据区域来处理其他分配。
指导是永远不要删除对象,直到完成所有对象的使用。有一些例外,其中成员函数删除它们操作的对象,确保在删除点之后不再有成员访问。但除了那些实际上有理由在成员中删除的案例外,不要这样做。
在您描述的多线程环境中,绝对肯定要将对象生命周期与对象使用协调,否则您可能会很难调试(平台相关和非确定性)行为。
答案 2 :(得分:0)
简短回答:你不应该这样做......你需要确保在删除它之前没有使用该对象。
就C ++标准指定的内容而言,它(可能)是未定义的行为 - 可能会发生意外情况。其基础是在对象被销毁之后使用对象的任何成员(函数或变量)是未定义的行为。当然,如果成员函数如下所示:
void foo::func()
{
for(;;)
{
// do nothing here
}
}
然后它不是未定义的行为,并且线程可以无限期地运行,没有任何不良影响,并且behvaiour(我相信)已经很好地定义(它只是保持运行)。
当然,线程1的执行肯定不会因为删除对象而停止。也就是说,除非对象实际包含线程1的线程对象 - 在这种情况下,线程对象的析构函数可能会杀死线程。
实际上,如果删除了对象,则释放内存,并且稍后可以在很短的时间内将内存重用于其他对象。取决于成员函数正在做什么,例如,它所引用的对象的哪些部分,以及它如何使用这些成员,它可能导致崩溃,或者它是否像x++;
那样(x
它是一个成员变量),它会修改一些不再是它的所有者的内存 - 这对调试来说非常棘手,因为它看起来像是随机改变其他对象......这绝对不是好事(和最有可能的是,它只会发生,但很难发现它何时出错)。
没有任何好处可以从中产生。
你必须确保该对象不以任何方式被删除。一种方法当然是为线程1提供线程对象,并终止该线程。
答案 3 :(得分:0)
未定义的行为是正确的答案。为避免这种情况,请考虑使用智能指针,例如:http://www.boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm或此:http://en.cppreference.com/w/cpp/memory/shared_ptr。它们具有引用计数机制,不允许您使用对象删除。