2017-03-08 62 views
0

我目前正在学习关于多线程的好的和不好的做法。据我的理解,在线程(t1)中创建一个局部变量并将一个指针传递给另一个线程(t2)是不好的做法。我知道t1的栈是动态的,所以t2可能并不总是访问正确的数据。但是,如果t2写入这个指针,t2可能执行错误的代码吗?由于此修改发生在t1堆栈中,它只能真正影响t1吗?当然,除非t2在执行后依赖于t1。有什么方法可以考虑这个问题?或者任何人都有关于每线程堆栈如何工作的好资源?在线程中创建变量和传递指针的问题

任何帮助将不胜感激,

谢谢!

+0

答案是,它取决于。你完全有权向另一个线程提供自己的堆栈,但是最好确保你同步线程以防止竞争条件,包括防止值超出范围,直到其他线程完成。 – paddy

回答

0

线程的堆栈只是为该线程保留的内存区域。这只是一个“传统”的东西。没有强制执行这种分离,并且内存区域实际上由所有线程共享。

所以,作为@paddy评论,你完全可以自由地路过线程A创建一个局部变量的地址到线程B.但是,你必须从线程A的创造功能没有回报,否则,堆栈内存将会(几乎肯定)被接下来的任何线程A重新使用。 (确保你理解你的语言/编译器如何使用堆栈是一个好主意。)

除此之外,该变量中的值的同步与线程之间共享的任何其他变量的同步完全相同。

从技术上讲,你是正确的,线程B简单地写入线程A的堆栈上的变量不能直接干扰线程B正在做的任何事情。但是,如果线程A 确实从创建变量的函数返回,那么线程B写入它实质上是将鱼雷发射到线程A的执行路径中的“随机”位置。内存现在可能在某个其他函数中保存了一些其他变量,或者现在可以保留线程A堆栈上某个函数的返回地址。

因此,由于线程A的损坏导致线程A的执行路径中存在未定义的行为,因此极有可能最终导致线程B的执行路径(以及任何其他线程)中的未定义行为/损坏。

试想想通过潜在影响:

  • 如果你要改变一个返回 地址的最低显著的字节,你会造成线程A恢复到什么情况良好是 代码的有效区域,但是而不是紧跟在 函数调用之后的代码,线程A在写入之前正在执行。

  • 如果你最终改变返回地址的更显著字节, 线程A可能会返回到其 虚拟地址空间的非可执行部分(可能导致异常和错误退出将于关闭所有线程)。

  • 如果你最终改变一个变量值(或保存的寄存器值),好了,谁知道会做什么?它 完全取决于被损坏的功能,以及它使用该内存位置的内容为 。您可能正在将数组索引更改为 越界值,或者将文件描述符更改为引用不同的打开文件,或将浮点值更改为NaN值。或者破坏线程A调用的库例程中的内存池指针。更改指针值,使其现在指向线程B的堆栈。

+0

谢谢!这个解释真的很有启发性,线程A的堆栈在那个地方持有返回地址的例子就是一个很好的例子。 – ka123444