Освобождение потенциально неинициализированных членов структуры - PullRequest
3 голосов
/ 25 января 2012

У меня есть такая структура,

typedef struct Player {
    char *name;
    char *heroID;
    char *heroName;
    int slotNo;
} Player;

Затем я определяю его как статически распределенный массив

Player players[10];

Моя программа может завершиться, когда я не полностью выделил все поля char* каждой структуры Player в players, и я решил, что освободлю любую выделенную память перед выходом, даже если современные операционные системы не работают. не требуется, потому что это хорошая практика программирования.

Однако я не могу просто просмотреть циклы players, free(player[i].name) и т. Д., Поскольку они могут быть неинициализированы.

Является ли единственный способ обойти эту проблему, вручную инициализировать каждый указатель на символ NULL после того, как я определил массив, а затем при освобождении памяти проверить, является ли указатель NULL или нет, чтобы решить, следует ли мне его освобождать?

Если это так, каков наилучший способ инициализации, для циклического и ручного назначения или определения значений, когда я объявляю массив игроков с помощью фигурных скобок. Или есть другой способ?

Ответы [ 4 ]

4 голосов
/ 25 января 2012

Это единственный способ обойти эту проблему: вручную инициализировать каждый указатель char на NULL после того, как я определил массив, а затем при освобождении памяти проверить, является ли указатель NULL или нет, чтобы решить, следует ли мне освобождатьэто?

Это определенно не единственный способ, но это самый распространенный и стандартный способ сделать это.Фактически, большинство программистов будут всегда инициализировать указатели на ноль, чтобы предотвратить ошибки сегментов.

Лучший способ инициализации - просто создать цикл for или memset все до нуля (или используйте calloc, что является самым простым).

3 голосов
/ 25 января 2012

Вы можете определить массив следующим образом:

Player players[10] = { 0 };

Это установит для всего массива и всех его членов значение 0 (что на самом деле NULL).

3 голосов
/ 25 января 2012

Вы можете создать указатель на структуру, используя calloc, поэтому все поля будут инициализированы в 0 (NULL).

Инициализация неиспользуемых указателей в NULL очень важно. Без этого вы находитесь на лучшем пути к ошибке сегмента

Edit (1)

Конечно, в вашем сценарии вы можете использовать какой-нибудь флаг bool is_used внутри каждой структуры, но вы можете сделать это лучше с помощью указателей NULL. Я не вижу причин делать это иначе.

1 голос
/ 25 января 2012

Поскольку у вашего массива статическая продолжительность хранения, он имеет неявный инициализатор.Ваш код эквивалентен

Player players[10] = { 0 };

Так что вы можете безопасно передавать эти указатели на free независимо от того, что произошло, когда вы их присвоили.

Сказав все это, если вызовmalloc не удалось, не удивляйтесь, если последующие вызовы free также не удаются.После сбоя при выделении кучи часто бывает достаточно прервать процесс.

...