我使用realloc来增加结构数组的内存量,而且它似乎根本没有增加。我已经阅读了与此相关的所有帖子,但我无法弄清楚我做错了什么。这是我的代码:
struct fileInfo {
char name[MAXNAMLEN];
struct stat stbuf;
};
...
struct fileInfo * newFileInfoPtr;
struct fileInfo * fileInfoPtr = (struct fileInfo *) realloc (NULL, sizeof (struct fileInfo));
// loop through directory to find all filenames
while ((direntPtr = readdir (dirFilePtr)) != NULL) {
(void) strcpy (direntName, filename);
(void) strcat (direntName, "/");
(void) strcat (direntName, direntPtr->d_name);
(void) strcat (direntName, "\0");
// check for vaild file
if (lstat (direntName, &st)) {
if (errno) {
(void) snprintf (buffer, BUFSIZ, STR_LSTAT_ERR);
perror (buffer);
}
exit (EXIT_FAILURE);
}
// reallocate memory for new fileInfo struct
newFileInfoPtr = (struct fileInfo *) realloc (fileInfoPtr,
(count+1) * sizeof (struct fileInfo));
// check for allocation success and increase count
if (newFileInfoPtr != NULL) {
(void) memset (newFileInfoPtr->name, NULL, MAXNAMLEN);
(void) strcpy (newFileInfoPtr->name, direntPtr->d_name);
newFileInfoPtr->stbuf = st;
fileInfoPtr = newFileInfoPtr;
count++;
} else {
if (errno) {
(void) snprintf (buffer, BUFSIZ, STR_ALLOC_ERR);
perror (buffer);
}
exit (EXIT_FAILURE);
}
...
direntPtr是指向已打开目录的指针,我正在读取其中所有文件的名称。那部分是有效的,因为我可以打印出每个条目的名称。我的问题是我最终得到的最终结构数组。我理解realloc你根据旧数组分配内存,将返回值赋给新指针,用信息填充新指针,并将旧指针设置为新指针。但是,在完成循环之后,fileInfoPtr只是一个结构。我可以访问索引0处的字段,但之后它们都是空的。我打印出每个索引的内存地址,它们都是一样的...... 谢谢你的帮助
答案 0 :(得分:2)
您的newFileInfoPtr
指向新分配的数组的第一个条目。通过memset
和strcpy
来电,您可以使用newFileInfoPtr->name
进行操作,这会覆盖第一个条目的名称。你想要
(void) memset (newFileInfoPtr[count].name, NULL, MAXNAMLEN);
(void) strcpy (newFileInfoPtr[count].name, direntPtr->d_name);
访问索引count
的最后一个条目(在递增之前)。
答案 1 :(得分:1)
你正在做一些正确的事情,并且realloc()
会出错。
我认为正确的是:
newFileInfoPtr = (struct fileInfo *) realloc(fileInfoPtr,
(count+1) * sizeof (struct fileInfo));
这样可以确保在分配失败时不会丢失分配的空间。但是,每次重新分配都很昂贵;它可以导致二次行为。您应该每次分配两倍的条目,或者是该想法的次要变体。
但是,在检查非null之后,正确的后续步骤之一是:
fileInfoPtr = newFileInfoPtr;
您还需要将fileInfoPtr
用作数组:
strcpy(FileInfoPtr[count].name, direntPtr->d_name);
我们可以就索引是count
还是count ± 1
进行协商;一般的想法是你需要使用struct fileInfo
数组作为数组,而不是总是使用数组的第0个元素。
如果是我的代码,我可能会使用如下结构:
typedef strut fileInfo FileInfo;
size_t count = 0;
size_t avail = 0;
FileInfo *fileInfoPtr = 0;
// loop through directory to find all filenames
while ((direntPtr = readdir(dirFilePtr)) != NULL)
{
snprintf(direntName, sizeof(direntName), "%s/%", filename, direntPtr->d_name);
if (lstat(direntName, &st))
{
int errnum = errno;
snprintf(buffer, sizeof(buffer), "Failed to lstat() %s (%d: %s)\n",
direntName, errnum, strerror(errnum));
perror(buffer);
exit(EXIT_FAILURE);
}
if (count >= avail)
{
size_t new_size = (avail + 1) * 2;
FileInfo *np = realloc(fileInfoPtr, new_size);
if (np == 0)
{
…handle error; release old fileInfoPtr…
exit(EXIT_FAILURE);
}
avail = new_size;
fileInfoPtr = np;
}
strcpy(fileInfoPtr[count].name, direntPtr->d_name);
InfoPtr[count].stbuf = st;
count++;
}
在循环结束时,count
会告诉您阵列中正在使用的条目数,avail
告诉您分配了多少条目。如果你担心太多的空间,你可以做一个最后的缩小realloc()
,使阵列成为你需要的确切尺寸。实际上很少需要这样做。
请注意,memset()
之前的strcpy()
不是必需的。