最初涉及多线程程序涉及的时候经常会出现一些令人难以思议的事情,用堆和栈分配一个变量可能在以后的执行中产生意想不到的结果,而这个结果的表现就是内存的非法被访问,导致内存的内容被更改。
理解这个现象的两个基本概念是:在一个进程的线程共享堆区,而进程中的线程各自维持自己堆栈。
另一运行机制就是如果声明一个成员变量 如 charName[200],随着这段代码调用的结束,Name在栈区的地址被释放,而如果是 char * Name = newchar[200];情况则完全不同,除非显示调用delete否则Name指向的地址不会被释放。
理解了线程对 堆栈的可见性,和内存管理机制就能推测出笔者伊始提出的现象。
用一个 实例来深入理解这种机制。
在线程 1 中,
A ()
{
B();
C();
}
B()
{
栈or 堆分配变量 V;
将V的地址插入 公共队列;
}
线程 2 中:
D()
{
while(1)
{
处理公共队列;
}
}
在B中如果用栈区即采用临时变量的机制分配声明V和堆区,而者的结果是不同的。如果用栈区,如果变量地址为Am1-Am2这么大,退出B调用时候这段地址被释放,C函数可能将这段内存改写;这样当D执行的时候,从内存Am1-Am2中读取的内容就是被改过的了。
而如果用New(堆)分配,则不会出现那样的情况,因为没有显示对用delete并且堆对于线程共享,即2线程可以看到1线程在堆里分配的东西,所以不会发生误写。
这个问题是笔者在公司实习的时候发现的,因为当时刚刚涉及多线程程序设计,操作系统中如此简单的话题困扰笔者很久,希望可以对初涉C++多线程的读者有所帮助!