2012-02-28 4 views
6
void foo() 
{ 
    char *c1 = "abc"; 
    static char *c2 = "abc"; 
    char *c3 = malloc(10); 
    strcpy(c3, "abc"); 
} 

В foo, я полагаю:локальные указатели, `static` указатели и указатели` malloc`

c1 является локальным указателем, поэтому он должен быть в стеке;

c2 - статический указатель, он должен находиться на куче;

c3 находится на куче.

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

stack   rodata   heap 
| |  |  |   | | 
| c1 |------>| "abc" |<--------| c2 | 
| .. |  |  | \  | .. | 
| |  |  | `------| c3 | 
| |  |  |   | | 

Мое предположение и график правильно?

Тем не менее, я не совсем понимаю, почему должно c3 быть на куче? c3 всего лишь char *, просто указав адрес (расположенный на куче), не делает c3 на куче, не так ли?

+1

Нет, c3 указывает на массив в куче, который теперь содержит «abc»; c2 должен находиться в BSS. c1, однако, находится в стеке. – tbert

+1

c3 находится в стеке, но указывает на кучу. – Matthias

ответ

8

Ваше предположение неверно. c3 не указывает на литературу "abc". Он указывает на возвращаемую память malloc, которую вы копируете.

Также c1 и c3 оба находятся в автоматическом хранилище (в стеке). Они являются указателями в области функций. Объекты c3 указывают на, однако, в динамическом хранилище (кучу), но c3 сам по себе нет.

Более правильный график:

stack   rodata   heap  global 
| |  |  |   |  | |  | 
| c1 |------>| "abc" |<--------------------| c2 | 
| c3 |------------------------>| "abc" | 
| |  |  |   |  | 
| |  |  |   |  | 
+0

'c2' находится в сегменте' .bss'? И это сегмент, где располагаются глобальные вары и статические вары? – Alcott

+0

@Alcott 'c2' находится в статическом хранилище (где статика и глобальные значения есть, да). –

+0

Место, где размещаются объекты статического хранения, часто называют компилятором .bss. Проверьте ссылку на wiki в своем ответе. – Lundin

4

Фактическая переменная, c3 находится в стеке, потому что это локальная переменная. Однако данные, которые указывают c3, будут находиться в куче, потому что указатель был создан с помощью malloc.

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

+1

Итак, жизнь 'c3' будет прекращена, когда' foo() 'заканчивается, правильно? Но если я не 'free c3', то пространство, выделенное' c3', не будет собрано, когда 'foo()' заканчивается, не так ли? – Alcott

+0

@ Алкотт правильно, я думаю, вы сейчас понимаете! –

+0

@Alcott no он не будет бесплатным() 'd, и у вас будет утечка памяти. – nos

-1

Это то, что ваша схема должна выглядеть следующим образом:

heap  stack  rodata  bss 
|  | |  | |  | |  | 
|"abc"|<-+ | c1 |--->|"abc"|<---| c2 | 
|  | | |  | |  | |  | 
|  | +-| c3 | |  | |  | 
|  | |  | |  | |  | 

c3 объявляется так же, как c1. Они оба находятся в стеке.

+0

@ Luchian: Отредактирован ответ –

1

c1 и c3 - указатели с автоматическим хранением. Эти 2 указателя живут в стеке вашей функции foo(). То, что они указывают на другое дело.

c2 является статичным и живет где-то в другом месте (обычно это не куча, а какая-то другая секция данных, действительная для всей продолжительности программы).

Оба c1 и c2 указывают на строковый литерал «abc». Обычно строковые литералы помещаются в раздел только для чтения, и аналогичные строки объединяются, поэтому c1 и c2 указывает на ту же память.

c3 указывает на память, выделенную malloc(), которая является памятью, обычно называемой «кучей». Затем вы копируете строку «abc» в эту память в куче.

+0

Вы, вероятно, имели в виду c3 в последнем абзаце, поэтому я взял libery для его редактирования. – Lundin

+0

Умм, в третьем абзаце все еще неверно. Вы лучше отредактируете это самостоятельно, затем я буду перенаправлять :) – Lundin

1

c1 - локальный указатель, поэтому он должен быть в стеке;

Исправить. Хотя он также может быть выделен в регистре CPU.

c2 - статический указатель, он должен находиться на куче;

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

Чтобы упростить статическую инициализацию, все такие объекты статической продолжительности хранения обычно помещаются в отдельную выделенную часть ОЗУ, часто называемую .bss. Маловероятно, что .bss будет помещен в стек.

c3 находится на куче.

Фактический указатель C3 находится в стеке, но содержимое, на которое оно указывает, находится на куче. Единственными переменными, которые находятся в куче, являются те, которые вы динамически выделяете с помощью malloc(). Ничего другого нет.

Мое предположение и график справа?

C1 правильный, указатель указывает на строковый литерал rodata, который хранится в секции только для чтения в памяти.

C2 неверен, так как он проживает в .bss. Он указывает на строковый литерал rodata, хотя, как и на вашем графике.

C3 неверен. Когда вы strcpy() что-то, вы делаете печатную копию строкового литерала в rodata и храните эту копию в куче в области, на которую указывает C3. Сам C3 находится на стеке.

EDIT: Не уверен, что этот график стоит, но здесь вы идете.

stack  .bss  rodata  heap 
| |  | | |  |  | | 
| c1 |-------------->| "abc" |  | | 
| |  | c2 |--->| "abc" |  | | 
| c3 |----------------------------->|abc | 
| |  | | |  |  | | 
+0

'Единственными переменными, которые находятся в куче, являются те, которые вы динамически выделяете с помощью malloc()', я не совсем понимаю это. Я думаю, все те, что я выделил с помощью 'malloc', - это просто память, но переменные - это просто идентификаторы, они могут указывать на память, выделенную' malloc', могут ли они быть в куче переменных? – Alcott

+0

@Alcott Действительно, фактический указатель выделяется в стеке. Он указывает на кучу. Возьмите эту структуру 'typedef struct {int x; } X_t; 'затем объявить указатель на него:' X_t * ptr; 'и затем выделить память' ptr = malloc (sizeof (X_t)); '. Теперь 'ptr' выделяется в стеке, но структура и его член' x' выделяются в куче. '& ptr-> x' даст вам адрес в куче. – Lundin

+0

Ха, красивая, вот и все. :-) – Alcott

0

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

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

Смежные вопросы