2011-11-06 25 views
7

今天我遇到了一個非常奇怪的問題。長話短說,我的函數返回一個值,調用者獲得不同的值。 某處在我的代碼,我不得不打電話:C函數更改返回值。損壞的堆棧?

Message* m = NULL; 
m = connection_receive(c); 

凡connection_receive定義如下:

Message* connection_receive(Connection* c) 
{ 
Message* k; 

    if (c->state == CON_STATE_AUTHENTICATED) 
    { 
     pthread_mutex_lock(&c->mutex_in); 

     if (g_queue_is_empty(c->in)) 
      k = NULL; 
     else 
      k = (Message*)g_queue_pop_head(c->in); 

     pthread_mutex_unlock(&c->mutex_in); 
     /* Until here, k is reachable and contains the correct data. */ 
     return k; 
    } 
    else 
     return NULL; 
} 

這裏有一個gdb的運行,我在返回之前和分配之後對對停止:

222   return k; 
(gdb) p k 
$1 = (Message *) 0x7ffff0000950 
(gdb) n 
226 } 
(gdb) n 
main() at src/main.c:57 
57    if (m) 
(gdb) p m 
$2 = (Message *) 0xfffffffff0000950 

當然,如果我們嘗試訪問0xfffffffff0000950,我們會得到分段錯誤。

如果我改變函數而不是返回一個值,使用第二個參數來傳遞它的值,但我想知道這個錯誤。

非常感謝。編號: 這可行,但不方便。我也想知道爲什麼會出現這種奇怪的錯誤。

void connection_receive2(Connection* c, Message** m) 
{ 
    if (c->state == CON_STATE_AUTHENTICATED) 
    { 
     pthread_mutex_lock(&c->mutex_in); 

     if (g_queue_is_empty(c->in)) 
      *m = NULL; 
     else 
      *m = (Message*)g_queue_pop_head(c->in); 

     pthread_mutex_unlock(&c->mutex_in); 
    } 
    else 
     *m = NULL; 
} 

編輯2: 已解決。謝謝大家。 問題是頭文件上的拼寫錯誤。 我不能使用 - 錯誤,因爲我需要做的事情,其中​​ 提出了一些警告,並在一個很大的輸出和大頭我錯過了。

+0

我曾經發生過一次。 'fin'顯示一個返回值,它存儲的變量顯示另一個值。重新編譯修復了它(甚至沒有改變源代碼);最好我能猜到的是一個依賴的對象文件沒有得到重新編譯,否則可能是一個(很少遇到)gcc中的錯誤。 – Kevin

+0

你需要把它解釋爲一個[SSCCE](http://sscce.org/),它演示了這個問題併發布了它 - 你發佈的代碼沒有問題;問題在於別處。 –

+0

@BrianRoach,我會看看我能做些什麼。這是一個很大的項目。 – Victor

回答

5
  1. 您的m是如何定義的?
  2. 您的來電者是否有權訪問正確的原型?
  3. 你在做什麼建築?

我懷疑這種類型不匹配,我的問題2是所有問題的關鍵。

你正在返回一個指針(我想是)48或64位。然而,調用者認爲會得到一個int,它可能有32位並且被簽名。在轉換回指針時,值會被符號擴展。

+4

+1,我很確定(2)是正確的。這就是你應該始終使用最大編譯警告集(gcc上的'-Wall -Werror')開發的原因,因爲它會捕獲這樣的事情。 –

+0

是的,返回值的下半部分完全相同是非常可疑的。 –

+0

@ fromherehere \t 對不起,我忘了說。我的「m」也是一個消息*。是的,調用者可以訪問相同的原型,我實際上正在測試模塊。既沒有--Wall也沒有-Wextra給我任何東西,它就像魅力一樣編譯。我正在構建並運行它在Fedora 15上,2.6.40.6-0 64bits – Victor

0

你是否在隊列中推入了一個malloc:ed對象?如果不是這樣,並且您推送了一個堆棧對象,那麼當您彈出物品時可能會出現奇怪的行爲。

+0

這是一個malloc化的對象。我編輯了原文,併發布了一個可以正常工作的等效定義。真奇怪! – Victor

0

我們面臨同樣的問題,根本原因是函數connection_receive()的隱式聲明。所以它被默認爲int,它被簽名並存儲在m中。