локальные указатели, "статические" указатели и указатели " malloc

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 ответов


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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

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