LINUX.ORG.RU

new и bad_alloc


0

2

Вот такой вот кусочек кода. Простите, если написал гавно, только начал переходить с си на си++.

#include <iostream>
#include <new>
#define BLOCK_SIZE 1024

int main ()
{
    char * a;
    unsigned long size = 0;
    for (size = 0;true;size += BLOCK_SIZE)
    {
        try
        {
            a = new char [BLOCK_SIZE];
        }
        catch (bad_alloc)
        {
            std::cout << a << " bytes allocated, can't allocate moar." << std::endl;
            return 1;
        }
    }
    return 0;
}
При компиляции получаем ошибку:
test.cpp:16: error: expected type-specifier before ‘bad_alloc’

Вроде как Шилдт пишет, что компилятор не обязательно должен обнулять указатель в случае ощибки, но вот bad_alloc дропнуть уж точно должен. А тут вроде как написано, что никаких таких исключений ему не известно даже. ЧЯДНТ?



Последнее исправление: nethoroth (всего исправлений: 1)
Ответ на: комментарий от nethoroth

Аналог $5 в местной валюте в кассу сайта внесите.

mv ★★★★★
()
Ответ на: комментарий от mv

Можно еще один дурацкий вопрос? Почему это процесс убивается еще до того, как обрабатывается исключение? Какой тогда смысл в его отлове?

nethoroth
() автор топика
Ответ на: комментарий от nethoroth

Ох, йопта... Чо-т не похоже, что вы с С переходите. В данном случае, у вас все на этапе компиляции прекратилось)

kulti ★★
()
Ответ на: комментарий от nethoroth

Можно еще один дурацкий вопрос? Почему это процесс убивается еще до того, как обрабатывается исключение? Какой тогда смысл в его отлове?

Это кернельный Out Of Memory Killer убивает, ему на try/catch крестовые пофиг. Ему на всё пофиг, он пришёл убивать.

Линуксовое ядро обычно настроено так, что позволяет выделить больше виртуальной памяти, чем есть в системе, но только если эта память не трогается записью. new вызывает конструктор, инициализирующий объект(ы), поэтому ядру приходится выделять реальную память. В какой-то момент твой процесс сжирает всю память, и ядро обламывается выделить ещё памяти. В таком случае поднимается OOM Killer и он убивает твой процесс. Раньше вообще кого попало убивал, жуть.

Если память выделять mmap()'ом, то на 64-битной системе можно сотни терабайт «выделить».

Ну и если система настроена так, что у юзерского процесса ограничен размер адресного пространства (или сегмента данных), то тогда исключение обрабатываться будет, когда ядро libc скажет: «Фиг тебе, жадная скотина, а не памяти!».

mv ★★★★★
()
Ответ на: комментарий от nethoroth

Ну если уж на то пошло - то все прекратилось еще на этапе нежелания написать using namespace std;.

using namespace std используют ламеры.

mv ★★★★★
()
Ответ на: комментарий от mv

Значит, действительно, не особо важно, отлавливать этот эксепшн или нет? Забавно. Спасибо. А где тут эта касса? Покопался, не нашел.

nethoroth
() автор топика
Ответ на: комментарий от mv

Собственно, потому и возникло нежелание - где-то это уже слышал.

nethoroth
() автор топика
Ответ на: комментарий от mv

using namespace std используют ламеры.

Чего плохого в этом в cpp файлах? Или писать std::map<std::string, std::pair< блаблабла - это хорошо и читаемо? В хедерах - ясное дело.

ratatosk
()

Даже если поймать экземпляр bad_alloc, что с ним потом делать?
1) сушить сухари и гасить программу - так она и так закроется с жалобой на неперехваченное исключение,
2) переключаться на некий дополнительный пул памяти - тогда программа сможет хромать ещё некоторое время, но когда кончится вспомогательный пул, то получаем ту же самую задачу,
3) продать^Wвыкинуть что-нибудь ненужное из кучи - так это можно и нужно делать без всяких bad_alloc'ов,
3) дефрагментировать каким-то макаром хип в надежде найти запас ещё-шнапса - штоу?

В общем, от анонимуса смысл данного действа ускользает.

anonymous
()
Ответ на: комментарий от simplex

Я спросил - чего плохого? Тайпдеф ради одного-двух раз удобств тоже не добавляет. Name clashes по-моему не так вероятны, чтобы загромождать код кучей std:: Если что-то возникнет - можно и убрать в конце концов. Вероятность, что это скомпилится и будет гадить в рантайме явно около нуля. А если уж на то пошло, то и ADL может такого говна подкинуть, безо всяких using

ratatosk
()
Ответ на: комментарий от anonymous

>3) продать^Wвыкинуть что-нибудь ненужное из кучи - так это можно и нужно делать без всяких bad_alloc'ов,

А как, через set_new_handler? Це ж коллбек, не C++ вей.

yoghurt ★★★★★
()
Ответ на: комментарий от anonymous

Да это то понятно, речь шла о _ловле_ того момента, когда потребуется сбросить балласт.

yoghurt ★★★★★
()
Ответ на: комментарий от anonymous

Даже если поймать экземпляр bad_alloc, что с ним потом делать?

Например в GIMP-е пользователь выбрал «провести очень сложное и ресурсоёмкое преобразование на данном изображении».

GIMP его начал проводить, навыделял памяти, значит отрабатывает алгоритм, и на полпути памяти внезапно не хватило.

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

Плохой GIMP упадёт, похерив результаты работы за весь день.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

GIMP упадет, потому что g_malloc вылетает при нехватке памяти.

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

Даже создатели UNIX придумали panic, чтобы не делать таких сложных обработок.

simplex
()
Ответ на: комментарий от simplex

GIMP упадет, потому что g_malloc вылетает при нехватке памяти.

Я для примера написал.

Даже создатели UNIX придумали panic, чтобы не делать таких сложных обработок.

Плохо.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

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

Вообще же, меня немного смущает нетехнический термин «внезапно» - это как? Если виртуальная память перед началом операции была успешно выделена и инициализована процессом, то о какой «внезапности» в середине работы может идти речь?

anonymous
()
Ответ на: комментарий от nethoroth

Можно еще один дурацкий вопрос? Почему это процесс убивается еще до того, как обрабатывается исключение? Какой тогда смысл в его отлове?

А ты перепиши свою программу так как ниже и поймешь какой смысл:

#include <stdio.h>
#include <iostream>
#include <new>
#define BLOCK_SIZE 10

int main ()
{
    char * a;
    size_t size = 1;
    for (size = 1; true; size *= BLOCK_SIZE)
    {
        try
        {
            printf ("size: %llu\n", size);
            a = new char [size];
        }
        catch (std::bad_alloc)
        {
            std::cout << a << " bytes allocated, can't allocate moar." << std::endl;
            return 1;
        }
    }
    return 0;
}
quest ★★★★
()
Ответ на: комментарий от nethoroth

>Значит, действительно, не особо важно, отлавливать этот эксепшн или нет? Забавно.

Программа должна обрабатывать все возможные ошибки. ТОЧКА.

quest ★★★★
()
Ответ на: комментарий от anonymous

>В общем, от анонимуса смысл данного действа ускользает.

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

quest ★★★★
()
Ответ на: комментарий от zootcat

Простите, это был не совсем английский) К тому же там есть ошибка явно более заметная - вместо a должен выводится size, конечно.

nethoroth
() автор топика
Ответ на: комментарий от quest

Черт, а в чем же прикол? Почему же в Вашем варианте исключение все-таки обрабатывается? Это из-за того, что OOMKiller не успевает дотянуться? Или тут есть какая-то скрытая джедайская техника, которая заставляет исключение обработаться до того, как OOMKiller все испортит?

nethoroth
() автор топика
Ответ на: комментарий от nethoroth

без разницы, просто теперь ты видишь что обрабатывать ошибки нужно)

quest ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.