Лучшие практики C, выделение стека и кучи

В последнее время я очень часто использую c и обнаружил, что мне действительно не нравится иметь дело с управлением памятью или, по крайней мере, мысль о том, что если я запрограммировал указатель, я должен освободить его, даже если это самая тривиальная вещь. Это привело меня к тому, что я выделил как можно больше в стеке и использовал & для определения его местоположения. Даже создание отдельных переменных int и inptr (у меня была проблема с lvalue с оператором & в макросах).

Я не нашел много мест, где мне приходилось иметь дело с передачей данных вверх (вверху / внизу), где они были размещены. В то же время мне нужно приличное количество ранних возвратов (и я бы предпочел избегать gotos). Что общего c мнением говорят? Есть ли очевидные признаки того, что я должен использовать тот или иной в конкретном случае.

P.S. Одна вещь, которая заставила меня немного волноваться, заключалась в том, что у меня недавно возникла проблема с повреждением памяти из-за использования неправильного sizeof для malloc, и я не заметил этого сразу, поскольку большинство моих путей кода сразу после этого момента не использовали кучу . Как вы думаете, насколько большой проблемой может быть такое сокрытие коррупции?


person Roman A. Taycher    schedule 29.01.2011    source источник
comment
stackoverflow.com/questions/102009/   -  person Sebastian Paaske Tørholm    schedule 29.01.2011
comment
Отказ от использования goto для очистки в C больше похож на слепую догму, чем на разумный стиль кодирования.   -  person    schedule 29.01.2011
comment
хотя эта ссылка связана, в C ++ все не так. Во-первых, не намного ли популярнее подсчет ссылок?   -  person Roman A. Taycher    schedule 29.01.2011
comment
Некоторые проекты могут не одобрять goto cleanup.   -  person Roman A. Taycher    schedule 29.01.2011


Ответы (4)


Вам следует использовать malloc, если:

  1. Вы передаете указатели на данные, отличные от static const, вверх по стеку вызовов, или
  2. вы выделяете переменные или просто большие объемы данных (иначе вы рискуете переполнить стек).

В других случаях распределение стека должно быть нормальным.

person Fred Foo    schedule 29.01.2011
comment
@Oli: нет, я действительно имею в виду не const. То есть передача указателя на static const память вверх по цепочке - это нормально, но передача указателя на static не-const память обычно является признаком плохого стиля / дизайна, отсутствия потоковой безопасности, сложности отладки и т. Д. - person Fred Foo; 29.01.2011
comment
Истинный. Но более серьезная проблема заключается в передаче указателей на данные стека! - person Oliver Charlesworth; 29.01.2011

Немного оскорбления: самый верный признак - когда у вас закончился стек.

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

person AndersK    schedule 29.01.2011
comment
Примечание: это только что произошло (вроде бы я поместил около 1 МБ? Материала вверху main и почему-то мне кажется, что я попытался записать в незаписываемую часть исполняемого образа. - person Roman A. Taycher; 19.03.2011

Хотя технически он не имеет прямого отношения к вопросу ОП, он находится в том же парке (что, как я считаю, является достаточным обоснованием для моего ответа).

Возможно, вам стоит взглянуть на «Boehm C Garbage Collector». Это программа, проверенная временем, и я без проблем пользовался ею много раз. Это позволяет вам эффективно использовать malloc для всего и просто забыть о соответствующем free.

person johne    schedule 29.01.2011
comment
C со сборщиком мусора - это не C - person Mandrake; 29.01.2011
comment
И Boehm GC не работает. У него есть фатальные, неразрешимые катастрофические утечки памяти. C + GC по сути невозможен. - person R.. GitHub STOP HELPING ICE; 29.01.2011

Распределение стека полезно, когда вам нужно иметь дело с небольшим объемом данных, и эти данные нужны только для одной функции. Если вместо этого вам нужно передавать указатели между функциями, вам лучше использовать malloc () для памяти в куче из-за того, что после выхода из функции ее стек может каждый раз перезаписываться. Наличие более 127 байтов локальных данных замедлит выполнение, поскольку, если смещение находится в пределах этого лимита, его можно включить в саму инструкцию (например, mov eax, [ebp - 4]), поэтому символьные буферы должны быть размещены в куче (если вы не уверены они не превышают этот предел). Еще кое-что о free () (за счет отрицательного голосования;): освобождение вашей памяти не требуется, если на самом деле ОС потребует обратно всю память, которую она предоставила вашему приложению, но это плохая практика программирования, признак лени и может вызвать утечку памяти или какие-либо ошибки.

person BlackBear    schedule 29.01.2011