Сколько памяти зарезервировано, когда я объявляю строку? - PullRequest
2 голосов
/ 07 апреля 2010

Что именно происходит с точки зрения памяти, когда я объявляю что-то вроде: char arr [4];

Сколько байтов зарезервировано для arr?

Как устроена пустая строка, когда я 'strcpy' строка длины 4 в arr?

Я писал программу для сокетов, и когда я попытался добавить суффикс NULL в arr [4] (то есть в 5-ю ячейку памяти), я в итоге заменил значения некоторых других переменных программы (переполнение) и попал в большой беспорядок.

Какие-либо описания того, как компиляторы (gcc - это то, что я использовал) управляют памятью?

Ответы [ 5 ]

2 голосов
/ 07 апреля 2010

sizeof(arr) байтов сохранено * (плюс любой отступ, который компилятор захочет обойти, хотя это не для массива как такового). В реализации со стеком это просто означает перемещение указателя стека sizeof(arr) байтов вниз. (Вот откуда берется хранилище. Именно поэтому автоматическое распределение выполняется быстро.)

'\0' не размещается. Если вы скопируете в него «abcd», вы получите переполнение буфера, потому что это занимает всего 5 байт, но у вас есть только 4. Вы вводите землю неопределенного поведения, и все может произойти.

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

* Что является sizeof(char) * 4. sizeof(char) равно всегда 1, поэтому 4 байта.

1 голос
/ 07 апреля 2010

Что именно происходит с точки зрения памяти, когда я объявляю что-то вроде: char arr [4];

4 * sizeof(char) байт стековой памяти зарезервировано для строки.

Как устроена пустая строка, когда я 'strcpy' строка длины 4 в arr?

Вы не можете.У вас может быть только 3 символа, 4-й (т.е. arr [3]) должен быть символом '\ 0' для правильной строки.

, когда я пытался добавить суффикс NULL в arr [4]

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

1 голос
/ 07 апреля 2010

В C вы запрашиваете - обычно - именно то, что вы получаете. char arr[4] - это ровно 4 байта.

Но что-либо в кавычках добавляет в конце «скрытый» ноль, поэтому char arr[] = "oops"; резервирует 5 байтов.

Таким образом, если вы сделаете это:

char arr[4];
strcpy(arr, "oops");

... вы скопируете 5 байтов (o o p s \0), когда зарезервировали место только для 4. Что бы ни случилось дальше, это непредсказуемо и часто катастрофично.

0 голосов
/ 07 апреля 2010

Когда вы делаете объявление типа char arr[4];, компилятор выделяет столько байтов, сколько вы просили, а именно четыре. Компилятор может выделить дополнительные ресурсы для обеспечения эффективного доступа к памяти, но, как правило, вы получаете именно то, что просили.

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

На самом деле это не функция gcc. Все компиляторы Си работают по существу одинаково.

0 голосов
/ 07 апреля 2010

Когда вы определяете переменную, например char arr[4], она резервирует ровно 4 байта для этой переменной. Как вы выяснили, письмо за пределами этой точки вызывает то, что стандарт называет «неопределенным поведением» - эвфемизмом «вы облажались - не делайте этого».

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

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