Когда разрешено не освобождать динамически выделенную память? - PullRequest
3 голосов
/ 11 февраля 2020

Я знаю, что любая динамически выделенная память ДОЛЖНА быть освобождена в конце ее использования, с free(). Однако у меня есть библиотека, которая предоставляет следующую функцию:

char *rsprintf_s(const char *format, ...);

Она делает то же самое, что и asprintf, но напрямую возвращает строку, которая была динамически сгенерирована в этой функции. Например:

int main()
{
    char *my_str = rsprintf_s("A number: %d, a string: %s.", 42, "StackOverflow");
    printf("`rsprintf_s` result: '%s'", my_str);
    return 0;
}

, которые выдают следующее: `rsprintf_s` result: 'Число: 42, строка:" StackOverflow "' .

Я представляю в этой программе есть утечка памяти, которая вынуждает меня сделать это:

int main()
{
    char *my_str = rsprintf_s("A number: %d, a string: %s.", 42, "StackOverflow");
    printf("`rsprintf_s` result: '%s'", my_str);
    free(my_str);
    return 0;
}

Однако, это идиоматическая c функция? Если он существует, то считается ли это незначительной проблемой, чтобы не освободить память в таком стиле? Я хотел бы знать, можно ли использовать такую ​​функцию, не беспокоясь об освобождении памяти каждый раз, хотя я сомневаюсь в этом.

Ответы [ 3 ]

4 голосов
/ 11 февраля 2020

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

Если rsprintf_s специально не скажет вам, что вы должны освободить то, что он возвращает, я бы не стал считать, что это так. Возможно, у него есть реализация, в которой даже не используется кучная память (возможно, он использует статически распределенную глобальную память, возможно, в разделе DATA или что-то в этом роде).

3 голосов
/ 11 февраля 2020

Я знаю, что любая динамически распределенная память ДОЛЖНА быть освобождена в конце ее использования, с free().

Нет. Не освобождение приводит к тому, что вашей программе остается меньше памяти для других целей. Это может (или не может) привести к тому, что объем памяти программы будет больше, чем в противном случае. В вопиющих, расширенных или экстремальных случаях (согласно оценке, зависящей от среды) это может означать, что недостаточно (виртуальной) памяти для обслуживания других приложений или для самой утечки. Но ни одна из этих вещей не означает, что вы должны освободить память. У вас всегда есть возможность принять последствия, если вы этого не сделаете.

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

И это приводит нас непосредственно к вашему примеру программы.

Однако, это идиоматическая c функция? Если он существует, то считается ли это незначительной проблемой, чтобы не освободить память в этом стиле кейса?

Я думаю, вы имели в виду "если он выходит ". Как уже говорилось выше, практически нет различий в практическом воздействии на программу или систему: освобождение вручную перед выходом из вызова верхнего уровня на main(), с одной стороны, и оставление его для очистки ОС.

Хотелось бы узнать, можно ли использовать такую ​​функцию, не беспокоясь об освобождении памяти каждый раз, хотя я в этом сомневаюсь.

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

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

1 голос
/ 11 февраля 2020

Если вы работаете в операционной системе, где неправильный процесс не может действительно принести много пассивного вреда, то на практике это нормально. Активный вред, такой как повреждение файлов, - это еще одна вещь, но оставление свободной памяти при выходе из программы не будет взаимодействовать с этими системными API. Таким образом, исключение свободной памяти при выходе из программы, в некотором смысле, всегда хорошо, когда программа работает в такой операционной системе (например, в любой современной настольной ОС).

С другой точки зрения, это не всегда хорошо. Причины этого включают в себя: «1003 *

  • » Это просто не очень умно намеренно писать непереносимый код, когда вам не нужно «1006» по какой-то причине, Вы никогда не знаете, что принесет будущее.
  • Быть неаккуратным с памятью, но не быть неаккуратным с другими вещами, это сложный образ мышления. Только не пренебрегайте своим кодом.
  • То, что сейчас завершается программой, может в конечном итоге стать просто функцией обработки ошибок и возобновить нормальную работу позже, а затем, во-первых, легко забыть исправить утечку памяти, и, кроме того, вам, возможно, придется много заниматься рефакторингом, когда вам вдруг понадобится доступ к указателю, который будет освобожден в месте, где ранее вы только что его уже выбросили.
  • Когда они видят утечки, другие программисты будут плохо думать обо всей программе и, как о расширении, о программисте, который ее написал.
  • В других языках, таких как C ++, освобождение памяти связано с вызовом кода очистки, такого как деструктор класса, и в свою очередь, например, flu sh может буферизовать и закрывать файлы, а если этого не сделать, могут остаться поврежденные файлы и т.д. c. Лучше не развивать вредные привычки с C, которые вам нужно отучить на другом языке.
...