2014-03-19 58 views
0

在C代碼,我有一個大型的C代碼,32位計算機上工作正常,但無法在64臺機器與的glibc損壞的雙向鏈表的錯誤,同時運行64位機

*** glibc detected *** ./XXX.exe: corrupted double-linked list:錯誤。

我已經運行Valgrind並使用打印語句準確查明錯誤來自哪裏,但對修復無能爲力。 實際代碼非常大,但我在這裏給出相關部分。希望有人能幫我解決它。 實際的錯誤從Buf_Close()模塊來它嘗試釋放Buf_elm_p p作爲if (p != NULL) free(p);

這些功能的主代碼調用的,我只是在這裏給這個因爲錯誤是在這裏的某個地方。從主代碼的調用順序是:

1. Buf_Init 2. Buf_New_p 3. Buf_Close

Buf_bf_p 
Buf_Init(size_t elm_size, 
     int nelm_buf, 
     long nbuf) 
/******************************************************************************* 
!C 
!Description: Buf_Init (buffer initialize) initializes buffer data structures 
and buffers. 

!Input Parameters: 
elm_size element size (bytes) 
nelm_buf number of elements per buffer 
nbuf  number of buffers 

!Output Parameters: 
(returns)  pointer to the buffer data structure 
       or NULL for an error return 
*****************************************************************************/ 
{ 
    Buf_bf_p bf; 
    long buf_size; 
    long ibuf; 

    /* Calculate buffer size and check */ 
    buf_size = ((long) elm_size) * nelm_buf; 

    /*Allocate the buffer data structure */ 
    if ((bf = (Buf_bf_p) malloc(sizeof(Buf_bf_t))) == NULL) 
    {Buf_Error(&BUF_NOMEMORY, "Init"); return NULL;} 
    bf->key = BUF_KEY; 
    bf->elm_size = elm_size; 
    bf->nelm_buf = nelm_buf; 
    bf->nbuf = nbuf; 
    bf->buf_size = buf_size; 
    bf->fp = NULL; 
    bf->access = NO_FILE; 
    bf->nbuf_alloc = 1; 
    bf->ibuf_end = 0; 
    bf->ibuf_newest = 0; 
    bf->ibuf_oldest = 0; 
    bf->nelm = 0; 

    /* Allocate the buffer status data structure */ 
    bf->nbstat = max(NBSTAT_START, bf->nbuf + 1); 
    if ((bf->bstat = (Buf_bstat_t *) 
    malloc(bf->nbstat * sizeof(Buf_bstat_t))) == NULL) 
    {Buf_Error(&BUF_NOMEMORY, "Init"); return NULL;} 

    /* Allocate the first buffer */ 
    bf->bstat[0].loc = MEM_ONLY; 
    if((bf->bstat[0].buf_p = (Buf_elm_p) malloc(bf->buf_size)) == NULL) 
    { Buf_Error(&BUF_NOMEMORY, "Init"); 
    return NULL; 
    } 
    else 
    { 
    /* initialize */ 
    memset(bf->bstat[0].buf_p, '\0', bf->buf_size); 
    } 

    bf->bstat[0].newer = -1; 
    bf->bstat[0].older = -1; 

    /* Initialize the rest of the buffer status array */ 
    printf("bf->nbstat %d\n", bf->nbstat); 
    for (ibuf = 1; ibuf < bf->nbstat; ibuf++) { 
    bf->bstat[ibuf].loc = NOT_ALLOC; 
    bf->bstat[ibuf].buf_p = NULL; 
    bf->bstat[ibuf].newer = -1; 
    bf->bstat[ibuf].older = -1; 
    bf->bstat[ibuf].initialized = 1; 
    } 

    return bf; 
} 

Buf_elm_p 
Buf_New_p(Buf_bf_p bf, 
      long *ielm) 
/******************************************************************************* 
!C 
!Description: Buf_New_p (new buffer element pointer) returns a memory 
location and element number of a new element; elements are number 
sequentially as they are allocated. 

!Input Parameters: 
bf  pointer to the buffer data structure 

!Output Parameters: 
ielm  new element number 
(returns)  pointer to memory location of new element 
       or NULL for error 
!Notes: 
    1. 'Buf_Init' must be called before this routine to initialize 
     the buffer data structure. 
    2. If there is no more space in memory and disk write access is allowed, 
     the oldest buffer is written to disk and the memory is re-used. 
    3. If the file is opened with 'read only' access this routine will return 
     an error. 

!END 
******************************************************************************/ 
{ 
    long ibuf, jelm, jbuf, kbuf; 
    long nbuf_cmplt; 
    Buf_elm_p p; 
    long dsk_loc, eof_loc; 


    /* New element number/location */ 
    *ielm = bf->nelm++; 
    ibuf = *ielm/bf->nelm_buf; 
    jelm = *ielm % bf->nelm_buf; 

    /* Are we at the past the end of the last buffer? */ 
    if (ibuf > bf->ibuf_end) { 

    if (ibuf != (bf->ibuf_end + 1)) 
     {Buf_Error(&BUF_BADBUF, "New_p"); return NULL;} 

    /* Re-allocate buffer status data structure if not large enough */ 
    if(ibuf >= bf->nbstat) 
    { 
     bf->nbstat += min(bf->nbstat, MAX_NEW_NBSTAT); 
     if((bf->bstat = realloc(bf->bstat, bf->nbstat * sizeof(Buf_bstat_t))) 
      == NULL) 
     { Buf_Error(&BUF_NOMEMORY, "New_p"); 
      return NULL; 
     } 
    } 

    if (bf->nbuf_alloc < bf->nbuf || bf->access == NO_FILE) { 

     /* Allocate a new buffer */ 
     if((p = (Buf_elm_p) malloc(bf->buf_size)) == NULL) 
     { Buf_Error(&BUF_NOMEMORY, "New_p"); 
     return NULL; 
     } 
     else 
     { 
     /* initialize */ 
     memset(p, '\0', bf->buf_size); 
     } 
     bf->nbuf_alloc++; 
     if (bf->nbuf < bf->nbuf_alloc) bf->nbuf = bf->nbuf_alloc; 

    } else { 

     /* Re-use an existing buffer */ 

     /* Get the oldest buffer */ 
     jbuf = bf->ibuf_oldest; 
     /* Delete oldest buffer from old/new pointer list */ 
     p = bf->bstat[jbuf].buf_p; 
     bf->ibuf_oldest = bf->bstat[jbuf].newer; 
     bf->bstat[bf->ibuf_oldest].older = -1; 

     bf->bstat[jbuf].buf_p = NULL; 
     bf->bstat[jbuf].older = -1; 
     bf->bstat[jbuf].newer = -1; 
     bf->bstat[jbuf].initialized = 1; 

    } 

    /* Put current buffer in old/new pointer list */ 
    bf->bstat[ibuf].loc = MEM_ONLY; 
    bf->bstat[ibuf].buf_p = p; 
    bf->bstat[ibuf].older = bf->ibuf_newest; 
    bf->bstat[ibuf].newer = -1; 
    bf->bstat[ibuf].initialized = 1; 

    bf->ibuf_end = ibuf; 
    bf->bstat[bf->ibuf_newest].newer = ibuf; 
    bf->ibuf_newest = ibuf; 

    } 

    /* Calculate pointer to memory location of element */ 
    p = (unsigned char *) bf->bstat[ibuf].buf_p + (jelm * bf->elm_size); 

    return p; 
} 


int 
Buf_Close(Buf_bf_p bf) 
/******************************************************************************* 
!C 
!Description: Buf_Close (buffer cache file close) writes the remainder of the 
cache to the disk cache file and closes the file and frees memory of the 
buffer data structure and buffers. 

!Input Parameters: 
bf  pointer to the buffer data structure 

Notes: 
    1. 'Buf_Create' or 'Buf_Open' must be called before this routine to open 
     the file. 

!END 
*****************************************************************************/ 
{ 
    int i; 
    long dsk_loc; 
    logical_t cmplt_flag; 
    /* int b; */ 
    Buf_elm_p p; 
    long ibuf, nelm_wrt; 
    int nb; 
    unsigned char header[HEADER_SIZE]; 

    /* Write remaining buffers which are still only in memory */ 
    for (ibuf = 0; ibuf < (bf->ibuf_end + 1); ibuf++) 
    /* for (ibuf = 0; ibuf < (bf->ibuf_end); ibuf++)*/{ 
    p = bf->bstat[ibuf].buf_p; 
    /* Free the buffer memory */ 
**THIS FOLLOWING LINE IS WHERE THE ERROR IS COMING FROM** 

**VALGRIND SHOWS `Conditional jump or move depends on uninitialised value(s)` ERROR** 

**BUT AM NOT SURE HOW `p` is coming out to be uninitialized`** 

if (p != NULL) free(p); 
} 

    /* Free the buffer status memory */ 
    free(bf->bstat); 

    /* Free the buffer cache data structure */ 
    bf->fp = (FILE *)NULL; 
    bf->key = 0; 
    free(bf); 

    printf("buf here 5\n"); 
    return BUF_NORMAL; 
} 
+0

如果它在32位機器上工作正常,而不是在64位機器上,問題可能出現在你的代碼中,當然不在glibc中。你用32位的valgrind運行它嗎?或者也許你在指針算術的某個地方有問題(假設指針是32位寬)? –

+0

是的,我知道這個問題在本身的某個地方,而不是glibc。此代碼最初是爲32位機器而設計的,我的感覺是可能需要做一些64位特定更改,而這些更改我不確定。 – srsci

回答

0

這一點很難通過靜態分析來理解你的程序邏輯。然而,Valgrind在 的場景下打印「條件跳轉或移動取決於未初始化的值」,其中程序試圖以可能影響程序外部可見行爲的方式使用未初始化的數據。 未初始化的數據源往往是:

  1. 程序中的局部變量尚未初始化。
  2. 在您(或構造函數)寫入內容之前,堆塊的內容(使用malloc,new或類似函數分配)。

要看到在程序上未初始化的數據源的信息,您可以使用 選項--track-起源= YES。所以,你可以按以下方式運行程序(./ a.out的):

的valgrind --tool = MEMCHECK --track-起源= YES ./a.out

這可能是有益的並提供更多有用的信息更接近實際的problem.You的來源可以從該位置找到有關它的更多詳細信息:

http://valgrind.org/docs/manual/mc-manual.html

+0

您還可以在valgrind報告錯誤的模塊中使用calloc()更改malloc(),並可以驗證一次。儘管memset()的大部分地方都是在malloc()之後調用的,但是memset()沒有被調用的情況下可能會出現某些特殊情況,可能會導致這種情況導致內容未初始化。 –

+0

我確實用'--track-origin = yes'運行了Valgrind,但輸出仍然不是很有幫助。另外如何使用'calloc'而不是'malloc'在這裏幫助?這是指針保持單位化的問題。無論您使用malloc還是calloc,指針都應該至少使用適當的地址初始化爲新分配的空間。 calloc的使用只會用零填充所有分配的空間。 – srsci

+0

如果你的邏輯是這樣的,你將分配內存,然後將(基地址)存儲到堆中的另一個內存中。現在,如果通過某種方式,如果您的第一次分配沒有發生,另一個內存仍然會嘗試釋放該內存,則可能會遇到此問題。因此,如果你使用calloc(),那麼即使你沒有進行第一次分配調用,你也將是安全的,因爲在使用第二個堆內存中的存儲地址釋放內存時,!null檢查將失敗。 –

3

我上,有很多的問題的做法,一個項目(目前正在朝着清潔他們了)。我遇到了這個錯誤,並仔細研究了所有我能想象到的問題,以找出問題所在,包括clang消毒劑,各種valgrind工具以及各種其他技巧。

問題:在一個線程中調用exit()的時間大約與返回的main()相同,因此所有全局/靜態構造函數都在兩個單獨的線程中同時啓動。我實際上有點惱火,我沒有儘早建立聯繫。

此錯誤也表現爲:

  • double free or corruption
  • 段錯誤/ SIG11與引起內exit()
  • 崩潰內部malloc_consolidate一個看起來像這樣的調用堆棧:

我猜子彈項目之後

#0 0xabcdabcd in malloc_consolidate() from /lib/libc.so.6 
#1 0xabcdabcd in _int_free() from /lib/libc.so.6 
#2 0xabcdabcd in operator delete (...) 
#3 0xabcdabcd in operator delete[] (...) 
(...) 

而且不能添加的代碼示例,我無法得到它的valgrind下運行時出現此問題 - 它是否是一個時機的問題,或者valgrind如何工作的一些神器隱藏了我可能永遠不知道的問題。

相關問題