2012-08-03 3 views
17

Если распределение malloc терпит неудачу, мы должны попробовать его снова?Что делать, если malloc не удается?

В чем-то вроде этого:

char* mystrdup(const char *s) 
{ 
    char *ab = NULL; 

    while(ab == NULL) { 
     ab=(char*)malloc(strlen(s)+1); 
    } 

    strcpy(ab, s); 
    return ab; 
} 

ли петля, а действительно для проверки распределения памяти?

ответ

0

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

3

Нет, никогда. Если malloc возвращает NULL, это указывает на ошибку, и вы должны, вероятно, отказаться.

22

В целом, современная реализация malloc() вернет NULL только как абсолютное последнее место, и попытка снова определенно не поможет. Единственное, что поможет, - освободить память, а затем повторить попытку. Если ваше приложение хранит какие-либо расходные ресурсы, настало время освободить их, а затем дать еще один снимок.

В некоторых средах полезной практикой является выделение небольшого объема памяти в качестве дневного фонда . Если malloc() когда-либо делает возвращение NULL, вы можете освободить этот фонд дождливого дня, а затем выделить все ресурсы, необходимые для обработки ошибки и выйти изящно. Это было обычной практикой при программировании со старым Macintosh Toolbox; если malloc() возвращено NULL, вы можете использовать это пространство для создания диалогового окна, чтобы сообщить о проблеме перед выходом.

6

В однопоточной программе «попытка снова», не освобождая память между попытками, не имеет практического смысла. Он будет цепляться навсегда.

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

+4

Это может иметь смысл даже в однопоточной программе, если причиной сбоя является исчерпание общей памяти в системе, а не только ограничение для каждого процесса, такое как размер виртуального адресного пространства или предел 'setrlimit' , –

0

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

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

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

2

Без споров о том, почему и когда это было бы полезно, попытки перераспределения в цикле могли работать, по крайней мере, в Windows с 64-битным кодом и настройками по умолчанию. Более того, это может приобрести удивительно дополнительную дополнительную виртуальную память. Хотя, не делайте этого в бесконечном цикле, но вместо этого используйте конечное число попыток. В качестве доказательства попробуйте следующий код, который имитирует утечку 1 Мб памяти. Вы должны запустить его в сборке Release, желательно не под отладчиком.

for (int i = 0; i < 10; i++) 
{ 
    size_t allocated = 0; 
    while (1) 
    { 
    void* p = malloc(1024 * 1024); 
    if (!p) 
     break; 

    allocated += 1; 
    } 

    //This prints only after malloc had failed. 
    std::cout << "Allocated: " << allocated << " Mb\n"; 
    //Sleep(1000); 
} 

На моей машине с 8 Гб оперативной памяти и управляемой системой подкачки, я получаю следующий вывод (построен с VS2013 для цели x64, протестирован на Windows 7 Pro):

Allocated: 14075 Mb 
Allocated: 16 Mb 
Allocated: 2392 Mb 
Allocated: 3 Mb 
Allocated: 2791 Mb 
Allocated: 16 Mb 
Allocated: 3172 Mb 
Allocated: 16 Mb 
Allocated: 3651 Mb 
Allocated: 15 Mb 

Я не» t знать точную причину такого поведения, но кажется, что отчисления начинают сбой после того, как изменение размера профайла не может идти в ногу с запросами. На моей машине файл подкачки вырос с 8 до 20 Гб после этого цикла (сбрасывается до 8 ГБ после выхода программы).

Смежные вопросы