2011-03-17 23 views
5

我在信號處理程序中調用了一些C++函數,並且我的程序被分段錯誤終止。 當我使用gdb進行檢查時,memcpy()函數是我得到SIGSEGV的地方。 我想知道如果memcpy()是否是可重入函數?memcpy()函數是否可重入?

+0

看看信號處理程序獲取指針值和它使用的長度。 'memcpy'是安全的,但是如果你做了'free(somestruct-> data)之類的東西, somestruct-> data = 0; somestruct-> len = 0;'當然,信號可能會在中間發生。 – 2011-03-17 10:47:13

回答

1

我不明白它爲什麼不能重入。我不確定,但我認爲它基於您使用的庫很多。

11

除了最高度嵌入的平臺之外,它都是可重入的。你提到SIGSEGV,所以我認爲它不是其中之一。在這種情況下,很可能memcpy()不是罪魁禍首:它是調用者的錯。如果你問memcpy()複製錯誤的指針(或壞的長度),那麼它會成爲錯誤的指針。你可以很容易地做到這一點:

memcpy(NULL, NULL, 123456789); 

這會導致SIGSEGV,它會告訴你的memcpy()造成的。當然,這不是memcpy的錯 - 只是做你說的。你的信號處理程序用奇怪的東西來調用它。回調(在gdb或任何你有的工具中)到調用者的站點應該顯示你所調用的內容。如果不這樣做,只需輸出傳遞給memcpy的參數即可。

+2

Posix說memcpy不能從信號處理程序調用。實際上,它可能有用。大部分時間,至少。但一點也不能保證。 – 2011-03-17 10:48:37

+1

@James:我想,檢查方法是用明顯的循環替換對'memcpy'的調用,看看segfault是否仍然存在。如果它消失,那麼'memcpy'不是異步信號安全的。如果不是這樣,那麼或者問題出在其他地方,那就是實際的拷貝,否則它對於'char'訪問不是信號原子而是微妙的。 – 2011-03-17 11:15:32

+1

@詹姆斯這是非常令人驚訝的。我找不到memcpy()不是信號安全的(甚至來自opengroup)。在某些微控制器/ DSP架構上,由於其局部變量具有靜態位置,因此它不是可重入的,但我無法想象如何在不嘗試真正努力的情況下使其在其他架構上變得不安全。你有鏈接嗎? – 2011-03-17 17:33:04

2

有關(非)折返功能和信號處理程序(只要到GNU C庫相關的)一些相關的信息可以在http://www.gnu.org/s/libc/manual/html_node/Nonreentrancy.html#Nonreentrancy發現:

這部分似乎是你的問題尤爲重要:

  • 「僅從內存對象讀取是安全的,只要您可以處理信號可以傳遞時可能出現在對象中的任何值。請記住,對某些數據類型的分配需要多於一個指令,這意味着處理程序可以運行「在...中間」如果其類型不是原子的,則將其分配給該變量。「

  • 「只要數據突然改變,在處理程序運行的任何時候都不會干擾任何事情,僅僅寫入內存對象是安全的。」

0

除非memcpy被實施,它是可重入的。它只適用於你給它的東西 - 指針和長度值。所有參數都按值傳遞,所以一旦該函數被激活,這些值不會在其堆棧幀上發生變化,無論信號和/或其他線程如何。

0

我認爲問題在於,您正在使用memcpy函數的參數爲​​無效(或已刪除)指針,請仔細檢查您的代碼。

問候。