Похоже, что я неправильно прочитал код; нет утечки памяти, но возникла проблема в том, что BLUEPIXYnoted.
Вот мой продезинфицировать, завершен, тестируются valgrind
-clean кода:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
enum { MAX_LENGTH_OF_STRING = 256 };
static int checkHowManyFiles(const char *path)
{
assert(path != 0);
return 100;
}
static void oom(void)
{
fprintf(stderr, "Out of memory!\n");
exit(EXIT_FAILURE);
}
static void dynamicFunc(char** arr, int length)
{
int i = 0;
for (; i < length; i++)
{
if ((arr[i] = calloc(MAX_LENGTH_OF_STRING,sizeof(char))) == 0)
oom();
}
}
enum { NUMBER_OF_GRABADGE_FILES = 2 };
static int openDirectory(DIR * dir, char** arr, int num_files)
{
int flag = 0;
int i = 0;
struct dirent *ent;
if ((dir== NULL))
{
printf("Sorry can't open the directory\n");
flag = -1;
}
else
{
/* Skip . and .. */
for (i = 0; i < NUMBER_OF_GRABADGE_FILES; i++)
{
if (readdir(dir) == 0)
break;
}
for (i = 0; i < num_files && (ent = readdir(dir)) != NULL; i++)
{
/* d_namlen is not mandated by POSIX (only d_name, d_ino are) */
size_t namlen = strlen(ent->d_name) + 1;
arr[i] = realloc(arr[i], namlen);
if (arr[i] == 0)
oom();
strncpy(arr[i], ent->d_name, namlen);
printf("%d [%s]\n", i, arr[i]);
}
flag = i;
}
closedir(dir);
return flag;
}
static void freeFunc(char** arr, int length)
{
int i = 0;
for (; i < length; i++)
{
free(arr[i]);
}
free(arr);
}
static void orderTheFiles(char* path)
{
DIR * dir = opendir(path);
int length = checkHowManyFiles(path);
printf("Will assume there are no more than %d files\n", length);
if (length > 0)
{
char** arr = (char**)calloc(length,sizeof(char*));
dynamicFunc(arr, length);
int n = openDirectory(dir, arr, length);
printf("Actually got %d files\n", n);
freeFunc(arr, length);
}
else
closedir(dir);
}
int main(void)
{
orderTheFiles(".");
return 0;
}
Примечания пересмотренного интерфейс checkHowManyFiles()
- который переименован - и тривиальная реализация используется. В одной из директорий, где я тестировал код, есть более 100 файлов, и всего 5 в другой.
$ ../di19
==3546== Memcheck, a memory error detector
==3546== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3546== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==3546== Command: ../di19
==3546==
Will assume there are no more than 100 files
0 [aes]
1 [aes.c]
2 [aes.dSYM]
3 [aes.h]
4 [makefile]
Actually got 5 files
==3546==
==3546== HEAP SUMMARY:
==3546== in use at exit: 26,329 bytes in 187 blocks
==3546== total heap usage: 380 allocs, 193 frees, 63,291 bytes allocated
==3546==
==3546== LEAK SUMMARY:
==3546== definitely lost: 0 bytes in 0 blocks
==3546== indirectly lost: 0 bytes in 0 blocks
==3546== possibly lost: 0 bytes in 0 blocks
==3546== still reachable: 0 bytes in 0 blocks
==3546== suppressed: 26,329 bytes in 187 blocks
==3546==
==3546== For counts of detected and suppressed errors, rerun with: -v
==3546== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$
Код теперь убеждается, что он не выходит из пределов. Поскольку POSIX устанавливает только d_name
и d_ino
в структуре struct dirent
, я использовал strlen(ent->d_name)
для определения длины имени. Вы сами можете решить, важен ли для вас уровень мобильности - большинство систем, вероятно, обеспечивают d_namlen
. Обратите внимание, что функция openDirectory()
теперь сообщает, сколько файлов она помещает в массив, и сообщается, сколько места у нее доступно для работы.
Предварительное выделение строк на самом деле в основном впустую. Если бы это был мой код, я бы просто использовал calloc()
для массива (нулевых) указателей, а затем использовал strdup()
для копирования имен. И я, вероятно, увеличил бы массив указателей динамически по мере необходимости.
Где код 'freeFunction'? – kfx
Как мы ожидаем, чтобы помочь вам отладить 'freeFunc()', если вы не показываете нам код? –
'strncpy (arr [i], ent-> d_name, MAX_LENGTH_OF_STRING);': 'MAX_LENGTH_OF_STRING' выглядит плохо. – BLUEPIXY