我目前正在学习有关多线程的好的和坏的做法。根据我的理解,在线程(t1)中创建局部变量并将指向它的指针传递给另一个线程(t2)是不好的做法。我知道t1的堆栈是动态的,因此t2可能并不总是访问正确的数据。但是,如果t2写入此指针,那么t2可能执行错误的代码吗?由于这种修改发生在t1的堆栈中,它只能真正影响t1吗?当然,除非t2在执行后依赖于t1。我有什么方法可以考虑这个问题?或者任何人都有关于每线程堆栈如何工作的任何好资源?
任何帮助将不胜感激,
谢谢!
答案 0 :(得分:0)
线程的堆栈只是为该线程保留的内存区域。它只是一个传统的"但是事情。没有强制执行该分离,并且内存区域实际上由所有线程共享。
因此,正如@paddy评论的那样,您可以完全自由地将线程A创建的局部变量的地址传递给线程B.但是,您必须不从创建函数返回在线程A中。否则,该堆栈内存将(几乎可以肯定)被A接下来的任何线程重用。 (确保您了解语言/编译器如何使用堆栈是一个好主意。)
除此之外,该变量中值的同步与线程之间共享的任何其他变量完全相同。
从技术上讲,你可以纠正线程B只是简单地写一个线程A上的变量,堆栈不能直接扰乱线程B正在做的任何事情。但是,如果线程A 从创建变量的函数返回,则线程B写入它实际上是将一个鱼雷发射到"随机"线程A的执行路径中的位置。内存现在可能在某个其他函数中保存了一些其他变量,或者现在可以在线程A的堆栈中保存某个函数的返回地址。
因此,由于线程A的损坏导致线程A的执行路径中的未定义行为,因此极有可能最终导致线程B的执行路径中的未定义行为/损坏(以及任何其他线程)。
想想潜在的影响:
如果要更改返回的最低有效字节 地址,您将导致线程A返回到可能的状态 一个有效的代码区域,但不紧随其后的代码 函数调用,线程A在写入之前执行。
如果您最终更改了返回地址的更重要字节, 线程A很可能返回其不可执行部分 虚拟地址空间(可能导致异常和错误退出,这将取消所有线程)。
如果您最终更改变量值(或保存的寄存器值),那么,谁知道它会做什么?它 完全取决于被破坏的功能和它是什么 使用该内存位置。您可以将数组索引更改为 越界值,或引用a的文件描述符 不同的打开文件,或浮点值到NaN值。或者破坏由线程A调用的库例程内的内存池指针。或更改指针值,使其现在指向线程B的堆栈。