it-roy-ru.com

Malloc () инициализирует выделенный массив нулем?

Вот код, который я использую:

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

int main() {
    int *arr;
    int sz = 100000;
    arr = (int *)malloc(sz * sizeof(int));

    int i;
    for (i = 0; i < sz; ++i) {
        if (arr[i] != 0) {
            printf("OK\n");
            break;
        }
    }

    free(arr);
    return 0;
}

Программа не печатает OK. malloc не должен инициализировать выделенную память нулем. Почему это происходит?

5
devil0150

Страница руководства malloc говорит:

Функция malloc () распределяет байты размера и возвращает указатель на выделенная память. Память не инициализирована. Если размер равен 0, тогда malloc () возвращает либо NULL, либо уникальное значение указателя, которое может позже будет успешно передан free ().

Таким образом, malloc() возвращает неинициализированную память, содержимое которой является неопределенным.

 if (arr[i] != 0)

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

9
M.S Chaudhari

malloc не должен инициализировать выделенную память нулем. 

Память, выделенная malloc, не инициализирована. Ценность в этих местах неопределенна. В этом случае доступ к этой памяти может привести к неопределенному поведению, если значение в этом месте должно быть представлением прерывания для типа. 

n1570-§6.2.6.1 (p5):

Определенные представления объекта не должны представлять значение типа объекта. Если сохраненное значение объекта имеет такое представление и читается выражением lvalue, которое не имеет символьного типа, поведение не определено. [...]

и сноска говорит: 

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

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

6
haccks

malloc не должен инициализировать выделенную память нулем. Почему это происходит?

Вот как это было разработано более 40 лет назад.

Но в то же время была создана функция calloc() , которая инициализирует выделенную память нулем, и это рекомендуемый способ выделения памяти для массивов.

Линия:

arr = (int *)malloc(sz * sizeof(int));

Должен прочесть:

arr = calloc(sz, sizeof(int));

Если вы изучаете C из старой книги, она учит вас всегда приводить значение, возвращаемое malloc() или calloc() (void *) к типу переменной, которой вы присваиваете значение (int * в вашем случае). Это устарело, если значение, возвращаемое malloc() или calloc(), непосредственно назначено переменной, современные версии C больше не нуждаются в приведении.

3
axiac

Из стандарта C 7.22.3.4:

Синопсис

#include <stdlib.h>
void *malloc(size_t size);

Описание

Функция malloc выделяет пространство для объекта, размер которого составляет определяется по размеру и значение которого является неопределенным.

Значение является неопределенным . Таким образом, каждый компилятор может вести себя так, как хочет. Например, в Microsoft Visual C++ в режиме Debug область выделенной памяти с помощью malloc() полностью установлена ​​на 0xCDCDCDCD, а в режиме Release она является случайной. В современных версиях GCC это значение равно 0x000000, если вы не включаете оптимизацию кода, и случайное в противном случае. Я не знаю о других компиляторах, но вы поняли идею.

2
Ryan B.

void *malloc(size_t size) просто должен оставить в стороне указанное количество места. Это все. Нет никаких гарантий относительно того, что будет присутствовать в этом пространстве.

Цитируется из справочных страниц:

Функция malloc() распределяет байты размера и возвращает указатель на выделенная память. Память не инициализирована. Если size равен 0, затем malloc() возвращает либо NULL, либо уникальное значение указателя, которое может позже будет успешно передан free().

Помимо calloc() вы можете использовать функцию memset() для обнуления блока памяти.

2
babon

При первом вызове malloc(3) он запрашивает у операционной системы память для кучи.

По соображениям безопасности ядро ​​unix/linux (и многие другие операционные системы) обычно обнуляет содержимое страницы, которое должно быть передано процессу, поэтому ни один процесс не может получить доступ к предыдущему содержимому этой памяти и делать с ним неприятные вещи (например, поиск старые пароли или подобные вещи).

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

0
Luis Colorado