【发布时间】:2014-03-19 16:48:39
【问题描述】:
我有一个大型 C 代码,在 32 位机器上运行良好,但在 64 位机器上却失败了
*** glibc detected *** ./XXX.exe: corrupted double-linked list: 错误。
我已经运行 Valgrind 并使用 print 语句来准确查明错误的来源,但对修复一无所知。
实际代码非常大,但我在这里给出了相关部分。希望有人可以帮我解决它。
实际错误来自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;
}
【问题讨论】:
-
如果它在 32 位机器上运行良好而不在 64 位机器上运行良好,则问题可能出在您的代码中,当然不在 glibc 中。您是否在 32 位上使用 valgrind 运行它?或者你在某个地方的指针运算有问题(假设指针是 32 位宽)?
-
是的,我知道问题出在它本身的某个地方,而不是在 glibc 中。这段代码最初是为 32 位机器设计的,我的感觉是可能需要进行一些 64 位特定的更改,我不确定。
标签: c linked-list 64-bit glibc memory-corruption