c ++: определение локального массива по сравнению с вызовом malloc - PullRequest
6 голосов
/ 17 июля 2010

Какая разница между:

somefunction() {  
    ...  
    char *output;   
    output = (char *) malloc((len * 2) + 1);  
    ...  
}  

и это:

somefunction() {  
    ...  
    char output[(len * 2) + 1];  
    ...  
}  

Когда один более уместен, чем другой?

спасибо всем за ваши ответы. вот резюме:

  1. ех. 1 - куча выделения
  2. ех. 2 - это выделение стека
  3. размер стека ограничен, используйте его для меньших выделений
  4. вам нужно освободить выделение кучи, иначе оно будет вытекать
  5. выделение стека недоступно после выхода из функции
  6. выделение кучи доступно до тех пор, пока вы не освободите его (или приложение не закроется)
  7. VLA не являются частью стандарта C ++

исправления приветствуются.

Вот некоторые объяснения разницы между кучей и стеком:
Что и где находится стек и куча?

Ответы [ 5 ]

6 голосов
/ 17 июля 2010

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

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

5 голосов
/ 17 июля 2010

Первый пример выделяет блок памяти из кучи.Второй выделяет хранилище из стека.Разница становится видимой, когда вы возвращаете вывод из somefunction ().Динамически распределенное хранилище все еще доступно для вашего использования, но хранилище на основе стека во втором примере, ну, нигде.Вы все еще можете записывать в это хранилище и читать его некоторое время, пока в следующий раз вы не вызовете функцию, и тогда хранилище будет перезаписано случайным образом с адресами возврата, аргументами и т. Д.другие странные вещи, происходящие с кодом в этом вопросе тоже.Во-первых, если это программа на С ++, вы бы хотели использовать new вместо malloc (), чтобы вы сказали:

output = new char[len+1];

А что в любом случае с len * 2 + 1?Может быть, это что-то особенное в вашем коде, но я предполагаю, что вы хотите выделить символы Юникода или многобайтовые символы.Если это юникод, нулевое завершение занимает два байта так же, как каждый символ, и char является неправильным типом, являющимся 8-битными байтами в большинстве компиляторов.Если он многобайтовый, тогда все ставки отменены.

5 голосов
/ 17 июля 2010

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

Локальные переменные хранятся в стеке, размер которого гораздо больше, чем в куче, куда идут массивы, выделенные с помощью malloc.Я обычно хожу на что-либо> 16 байт, помещаемых в кучу, но у вас есть немного больше гибкости, чем это.Только не размещайте местных жителей в диапазоне размеров кб / мб - они принадлежат куче.

3 голосов
/ 17 июля 2010

Сначала немного терминологии:

  • Первый пример называется выделение кучи .
  • Второй образец называется выделение стека .

Общее правило: размещать в стеке, если:

  1. Необходимый размер массива неизвестен во время компиляции.
  2. Требуемый размер превышает 10% от общего размера стека. Размер стека по умолчанию в Windows и Linux обычно составляет 1 или 2 МБ. Таким образом, ваш локальный массив не должен превышать 100 000 байт.
1 голос
/ 17 июля 2010

Вы пометили свой вопрос как C ++, так и C, но второе решение не разрешено в C ++.Массивы переменной длины разрешены только в C (99).

Если предположить, что len является константой, оба сработают.

malloc () (и C ++ 'new')Выделите память в куче, что означает, что вы должны освободить () (или, если вы выделили 'new', 'delete') буфер, или память никогда не будет восстановлена ​​(утечка).

последний выделяет массив в стеке и исчезнет, ​​когда выйдет из области видимости.Это означает, что вы не можете возвращать указатели на буфер вне области, в которой он выделен.

Первый вариант полезен, когда вы хотите передать блок памяти (но в C ++ лучше всего управлять с помощью RAIIкласс, а не вручную), хотя последний лучше всего подходит для небольших массивов фиксированного размера, которые должны существовать только в одной области.

Наконец, вы можете пометить массив, выделенный в стеке, как «статический» для принятияон выходит из стека и попадает в раздел глобальных данных:

static char output[(len * 2) + 1];

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

Наконец, не используйте malloc в C ++, если у вас нет действительно веской причины (то есть, realloc).Вместо этого используйте «новый» и сопровождающий «удалить».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...