локальные указатели, `статические` указатели и` malloc` указатели - PullRequest
6 голосов
/ 28 февраля 2012
void foo()
{
    char *c1 = "abc";
    static char *c2 = "abc";
    char *c3 = malloc(10);
    strcpy(c3, "abc");
}

В foo я предполагаю:

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

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

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

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

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

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

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

Ответы [ 6 ]

9 голосов
/ 28 февраля 2012

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

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

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

 stack         rodata           heap        global
|    |       |       |         |       |   |      |
| c1 |------>| "abc" |<--------------------|  c2  |
| c3 |------------------------>| "abc" |
|    |       |       |         |       |
|    |       |       |         |       |
4 голосов
/ 28 февраля 2012

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

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

1 голос
/ 28 февраля 2012

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

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

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

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

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: Не уверен, что стоит этот график, но вот вы.

 stack      .bss       rodata        heap
|    |     |    |    |       |      |    |
| c1 |-------------->| "abc" |      |    |
|    |     | c2 |--->| "abc" |      |    |
| c3 |----------------------------->|abc |
|    |     |    |    |       |      |    |
1 голос
/ 28 февраля 2012

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

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

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

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

0 голосов
/ 14 июля 2013

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

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

0 голосов
/ 28 февраля 2012

Вот как должна выглядеть ваша диаграмма:

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

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

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