Проблема с переменной char* malloc/free. Пустое содержимое в переменной получателя после использования free

Я работаю над пользовательским регистратором данных SD-карты, используя следующую функцию и структуру:

char *filenameCreator(const char *prefix, const char *num, bool addExtension)
{
    char *filename = (char *)malloc(13 * sizeof(char));
    const char *uScore = "_";
    strcpy(filename, prefix);
    strcat(filename, uScore);
    strcat(filename, num);
    if (addExtension)
    {
        const char *ext = LOGFILE_EXTENSION;
        strcat(filename, ext);
    }
    delete[] num;
    return filename;
}

где вывод будет сохранен в переменной следующего типа:

struct FileInfo
{
    const char *fileName;
    double fileSize;
};

с FileInfo fileToDelete; и глобальная переменная char* createdFilename = nullptr; для временного хранения выходных данных функции.

Проблема в том, что при использовании следующих функций fileToDelete.fileName ПУСТО:

createdFilename= filenameCreator("FILE", numericConverter(receivedIndexSATCOM), true);
fileToDelete.fileName = createdFilename;

free(createdFilename);    // похоже, очищает содержимое переменной, в которой хранилось имя файла, а именно fileToDelete.fileName
createdFilename = nullptr;

Я стараюсь придерживаться правил освобождения памяти, используемой переменными, выделенными с помощью malloc.

Обратите внимание, что если я НЕ ИСПОЛЬЗУЮ free(createdFilename), код работает нормально и fileName создается правильно. Однако меня беспокоит неопределенное поведение или ошибочные ответы.

Вот пример имени файла, успешно созданного без использования free():

Мне всегда нужно освобождать указатель после каждого использования? Почему содержимое пустое даже после присвоения содержимого другой переменной?

РЕДАКТИРОВАТЬ:

Пожалуйста, вместо того, чтобы ставить минусы моему вопросу, прокомментируйте, что в нем не так, и я постараюсь его улучшить. Будьте зрелыми.

, 👍0

Обсуждение

Смотрите принятый ответ здесь. https://stackoverflow.com/questions/37514873/clarify-dangling-pointer-in-cc, @Delta_G

не используйте динамическое выделение памяти. Передайте буфер в стеке в функцию, @Juraj

Вы можете почитать о причинах, по которым вы голосуете против. В вашем случае ваш вопрос не показывает никаких усилий по исследованию вашей проблемы, ни в Интернете, ни на этом сайте. Однако вы должны сделать это, прежде чем спрашивать. _(Отказ от ответственности: я не голосовал против.)_, @the busybee

@Juraj В качестве общего совета я не согласен. Есть веские причины для динамического выделения памяти, даже на Arduino. Это зависит от дизайна программного обеспечения., @the busybee

@thebusybee. Я имел в виду имя файла. Здесь нет веской причины, @Juraj

@thebusybee при всем уважении, как вы или кто-либо другой можете наверняка сказать, что "я не прилагаю усилий". Публикация почти в 2:30 утра по британскому времени после 8 часов непрерывного кодирования истощает умственно. Как я могу "показать усилия", не раздувая свой пост? Спасибо в любом случае, @Daniel Melendrez

Мы просто посмотрели на ваш вопрос, и все. Мы не можем видеть, что вы делаете еще, поэтому это не имеет для нас значения. В вашем посте нет никаких ссылок на то, как вы пытались решить **вашу** проблему самостоятельно и почему у вас ничего не получилось. Если вы считаете, что это раздувает ваш вопрос, ну, это помогает. В противном случае вы получите нерелевантные или вводящие в заблуждение ответы, которые потратят еще больше вашего и нашего времени., @the busybee


1 ответ


Лучший ответ:

3

То, что у вас есть, называется "Висячий указатель". Вы пытаетесь использовать указатель, указывающий на память, которая была освобождена и больше не содержит того, что, по вашему мнению, он делает.

Эта строка кода в функции filenameCreator:

char *имя_файла = (char *)malloc(13 * sizeof(char));

выделяет блок памяти в куче и сохраняет указатель на него. Позже в функции вы возвращаете этот указатель.

возврат имени файла;

Когда вы вызываете эту функцию:

createdFilename= filenameCreator("FILE", numericConverter(receivedIndexSATCOM), true);

Вы присваиваете это значение указателя новому указателю. Теперь createdFilename указывает на этот блок памяти, который вы выделили в функции.

Когда вы дойдете до этой строки:

free(созданоимя_файла);

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

Если вы попытаетесь использовать createdFilename позже, он все равно будет указывать на то же место в памяти. Но то, что вы там хранили, было освобождено. Его там больше нет.

Если вы намерены продолжать использовать это имя файла, то не освобождайте память, пока не закончите его использовать. Иногда это означает жизнь программы, а вы никогда не вызываете free.

Важно освобождать выделенную память, но только тогда, когда вы больше не будете ее использовать.

,

Спасибо за ваш подробный и профессиональный ответ. Теперь для меня это имеет абсолютный смысл. Эта "проблема" является частью огромного проекта, который истощает меня умственно, и я не могу ясно мыслить. Как кажется, не освобождение указателя не должно быть проблемой., @Daniel Melendrez

@DanielMelendrez Если вы выделяете указатель, вы должны освободить его, когда он больше не нужен. Проблема в вашем коде не в том, что он не освобождается, так как он уже освобожден, а указатель в fileToDelete.fileName недействителен, @KIIV