在最后几天调试多线程,其中一个线程正在删除另一个仍在使用的对象,我意识到如果我可以使'this'易变,问题会更容易和更快地诊断。它本可以将系统(Symbian OS)上的故障转储更改为更有用的信息。
那么,有什么理由说它不能或不应该是?
编辑: 因此,确实没有安全的方法来阻止或检查这种情况。如果说访问陈旧类指针的一个解决方案是拥有一个保存指针的全局变量,并且调用的任何函数应该是使用全局变量替换'this'的静态函数,这是否正确? / p>
static TAny* gGlobalPointer = NULL;
#define Harness static_cast<CSomeClass*>(gGlobalPointer);
class CSomeClass : public CBase
{
public:
static void DoSomething();
private:
int iMember;
};
void CSomeClass::DoSomething()
{
if (!Harness)
{
return;
}
Harness->iMember = 0;
}
因此,如果删除另一个线程并将全局指针置空,则会立即捕获它。
我认为这个问题的一个问题是,如果编译器缓存了Harness的值而不是每次使用时都检查它。
答案 0 :(得分:7)
此不是变量,而是常量。您可以更改 this 引用的对象,但不能更改 this 的值。因为常量永远不会改变,所以不需要将它们标记为易失性。
答案 1 :(得分:4)
它没有帮助:使变量volatile变量意味着编译器将确保它在每次访问时从内存中读取其值,但this
的值不会改变,即使是来自不同的上下文或相同,你删除它指向的对象。
答案 2 :(得分:2)
可以。只需将成员函数声明为volatile。
struct a
{
void foo() volatile {}
};
答案 3 :(得分:2)
答案 4 :(得分:0)
如果在删除时正在读取对象,这是一个明显的内存错误,并且与volatile无关。
volatile旨在阻止编译器“记住”内存中可能由不同线程更改的变量值,即阻止编译器优化。
e.g。如果您的类具有指针成员p并且您的方法正在访问:
p->a;
p->b;
等。并且p在“this”中是易变的,因此p->b
可以访问不同于p->a
时的对象
如果p已经被破坏,虽然“这个”被删除了,那么volatile将不会拯救你。据推测,你认为它会“无效”,但它不会。
顺便提一下,如果你的析构函数锁定互斥锁以便使用同一个对象保护另一个线程,那么这也是一个非常合理的规则,你就会遇到问题。您的析构函数可能会因为它从需要同步活动的外部对象中删除自己的存在而锁定,但不能保护自己的成员。