2017-03-08 60 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