Почему char Pointer сохраняет данные больше чем выделенная память в C? - PullRequest
0 голосов
/ 30 октября 2019

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

Также япытался найти размеры указателя до и после ввода. Может кто-нибудь помочь мне понять, что здесь происходит? Вывод сбивает меня с толку.

Посмотрите на этот код:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int limit;

    printf("Please enter the limit of your string - ");
    gets(&limit);

    char *text = (char*) malloc(limit*4);

    printf("\n\nThe size of text before input is %d bytes",sizeof(text));

    printf("\n\nPlease input your string - ");
    scanf("%[^\n]s",text);

    printf("\n\nYour string is %s",text);

    printf("\n\nThe size of char pointer text after input is %d bytes",sizeof(text));

    printf("\n\nThe size of text value after input is %d bytes",sizeof(*text));

    printf("\n\nThe size of ++text value after input is %d bytes",sizeof(++text));

    free(text);



    return 0;


}

Проверьте этот вывод: enter image description here

Ответы [ 2 ]

5 голосов
/ 30 октября 2019

Это работает, потому что malloc обычно не выделяет столько же байтов, сколько вы ему передаете. Он резервирует память несколькими «блоками». Обычно он резервирует больше памяти для «кэширования» ее для следующих вызовов malloc в качестве оптимизации. (это зависит от реализации), например, проверьте glibc malloc innerals .

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

Также я попытался найти размеры указателя до и после ввода. Может кто-нибудь помочь мне понять, что здесь происходит? Вывод сбивает меня с толку.

Размер указателя фиксирован для всех типов указателей в машине, обычно он составляет 4/8 байтов в зависимости от размера адреса. Это не имеет ничего общего с размером данных.

2 голосов
/ 30 октября 2019

Добро пожаловать в мир неопределенного поведения!

char *text = malloc(limit*4); ( не приводите malloc в C ) заставит text указать первый элемент массива размераlimit*4.

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

Здесь базовый системный вызов, вероятно, выделил полную страницу памяти (часто 4 КБ), и, как вы это сделалине использовался другой malloc, вы только что использовали память, принадлежащую процессу, но все еще официально не используется. Но не полагайтесь на это, и никогда не использует его в производственном коде.

И sizeof не имеет смысла для указателей. sizeof(text) равно sizeof(char *) (то же самое для sizeof(++text) по той же причине) и является размером указателя (обычно 2, 4 или 8 байт), а sizeof(*text) равно sizeof(char), которое по определению равно 1.

C уверен, что вы как программист знаете, сколько памяти вы запросили, и не будете пытаться использовать больше. Все что угодно может произойти, если вы это сделаете (включая ожидаемый результат), но не вините язык или компилятор, если он сломается: только вы будете виновны.

...