我正在使用C语言中的realloc()函数,但我对该函数的真正工作方式有疑问...
想象一下,我读取了一个包含整数列表的ASCII文件
$ cat liste.txt
1
2
3
我希望此列表存储在整数表中。这是我的代码,每次从文件中读取新值时都使用realloc()
int *table, *table_tmp;
int n;
int taille = 0;
while ( fscanf(fid, "%d", &n) != EOF)
{
table_tmp = (int *) realloc((void *) table, (taille+1)*sizeof(int));
if (table_tmp != NULL)
table = table_tmp;
*(table+taille) = n;
fprintf(stdout, "READ : %02d\tSTORED : %02d\n", n, *(table+taille));
taille++;
}
我的问题是:此函数如何知道表的实际大小?由于它只是一个指针,我以为我们不知道元素的数量对吗?我们通过taille变量明确跟踪当前大小,该变量在每一步都增加,并告诉我们读取*(table + k)可接受的最大值
realloc()函数将> ptr指向的内存块的大小更改为大小字节。从区域的开始到新旧大小的最小值之间的范围,内容将保持不变。
人重新分配
非常感谢您的回答:)
BR
答案 0 :(得分:1)
由操作系统或等效操作系统处理。 C标准不需要将有关大小的信息提供给程序员。
一种非常常见的方法是将信息存储在指针所指向的地址之前。
答案 1 :(得分:0)
感谢大家的快速回答。
根据您的建议,我在glibc源代码中进行了一些挖掘,并在此处提供了一些有关其完成方式的信息。
在malloc.c中定义realloc()
void *
__libc_realloc (void *oldmem, size_t bytes)
{
(...)
/* realloc of null is supposed to be same as malloc */
if (oldmem == 0)
return __libc_malloc (bytes);
/* chunk corresponding to oldmem */
const mchunkptr oldp = mem2chunk (oldmem);
/* its size */
const INTERNAL_SIZE_T oldsize = chunksize (oldp);
(...)
在同一文件中,我们可以看到mem2chunk是一个偏移指针的宏(具有负值,因此实际上似乎指向内存的大小存储在指针之前):
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
和SIZE_SZ在malloc_internal.h中定义
#ifndef INTERNAL_SIZE_T
# define INTERNAL_SIZE_T size_t
#endif
/* The corresponding word size. */
#define SIZE_SZ (sizeof (INTERNAL_SIZE_T))
回到malloc.c,我们终于可以找到chuncksize函数的定义,据我所知代码,该函数返回给定内存的大小。
/* Get size, ignoring use bits */
#define chunksize(p) (chunksize_nomask (p) & ~(SIZE_BITS))
/* Like chunksize, but do not mask SIZE_BITS. */
#define chunksize_nomask(p) ((p)->mchunk_size)
最后也是最后一步是找到mchunkptr结构的精确定义。 可悲的是,我没有设法在源代码中找到它……它应该要求更多的调查。.我发现的最接近的是以下内容(仍在malloc.c文件中):
/*
----------------------- Chunk representations -----------------------
*/
/*
This struct declaration is misleading (but accurate and necessary).
It declares a "view" into memory allowing access to necessary
fields at known offsets from a given base. See explanation below.
*/
struct malloc_chunk {
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk (if free). */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
struct malloc_chunk* bk_nextsize;
};
/*
malloc_chunk details:
(The following includes lightly edited explanations by Colin Plumb.)
Chunks of memory are maintained using a `boundary tag' method as
described in e.g., Knuth or Standish. (See the paper by Paul
Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a
survey of such techniques.) Sizes of free chunks are stored both
in the front of each chunk and at the end. This makes
consolidating fragmented chunks into bigger chunks very fast. The
size fields also hold bits representing whether chunks are free or
in use.
An allocated chunk looks like this:
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if unallocated (P clear) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk, in bytes |A|M|P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User data starts here... .
. .
. (malloc_usable_size() bytes) .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| (size of chunk, but used for application data) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of next chunk, in bytes |A|0|1|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+