Подтвердить что ты не робот

Как проверить сбои распределения памяти с новым оператором?

Совсем недавно я переключил язык моего проекта на использование С++ из C. С C я использовал malloc, и после этого я проверяю, был ли malloc успешным, но с С++ я использую "новый" для выделения памяти, и я хотел бы знать, как вы обычно проверяете отказ в распределении памяти.

Из моего поиска в Google я увидел nothrow, как показано ниже.

char *buf = new (nothrow)char[10];

Я также видел следующее.

try{} catch(bad_alloc&) {}

Но как насчет следующего? Я использую некоторые из процедур библиотеки chrome для использования интеллектуальных указателей.

Например, у меня есть код следующим образом.

scoped_array<char> buf(new char[MAX_BUF]);

Замечательно использовать интеллектуальные указатели, но я просто не уверен, как проверить, успешно ли выделено выделение памяти. Нужно ли мне разбивать на два отдельных заявления с помощью nothrow или try/catch? Как вы обычно делаете эти проверки на С++?

Любые советы будут оценены.

4b9b3361

Ответ 1

Ну, вы вызываете новое, которое бросает bad_alloc, поэтому вы должны его поймать:

try
{
    scoped_array<char> buf(new char[MAX_BUF]);
    ...
}
catch(std::bad_alloc&) 
{
    ...
}

или

scoped_array<char> buf(new(nothrow) char[MAX_BUF]);
if(!buf)
{
   //allocation failed
}

Я имею в виду, по моему мнению, что интеллектуальные указатели распространяют исключения. Поэтому, если вы выделяете память обычным бросанием нового, вы должны поймать исключение. Если вы назначаете nothrow new, то вы должны проверить nullptr. В любом случае интеллектуальные указатели ничего не добавляют к этой логике

Ответ 2

Я ненавижу это говорить, но IMO, вы идете в неправильном направлении (и, к сожалению, другие ответы, которые вы получили, на самом деле не указали вам в правильном направлении).

Вместо того, чтобы выбирать между различными вариантами интеллектуального указателя и/или нормального варианта vs nothrow new, вам, вероятно, потребуется, по крайней мере, еще два шага назад от того, что вы делаете, и заменить динамические данные, управляемые вручную структуры с коллекциями. Это не всегда может быть правильным выбором, но, по крайней мере, по моему опыту, это правильный путь гораздо чаще, чем нет. Стандартная библиотека имеет ряд возможностей (вектор, дека, список, набор и т.д.), И есть неплохие шансы, что вы можете использовать один из них, а не напрямую обращаться с new и компанией.

По умолчанию они будут использовать распределитель, который заканчивает использование обычного (метательного) варианта new. Поэтому вы обычно хотите разместить большинство кода в блоке try на довольно высоком уровне и иметь предложение catch, которое имеет дело с тем, что там не хватает памяти.

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

Ответ 3

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

Стандартный new оператор бросает исключение std::bad_alloc при сбое, и это можно обрабатывать как обычное исключение

try {
  char* c = new char[100];
} catch (std::bad_alloc&) {
  // Handle error
}

Или альтернатива nothrow версия new просто вернет NULL при ошибке

char* c = new (std::nothrow) char[100];
if (!c) {
  // Handle error
}

Мне любопытно, что вы планируете делать, когда распределение не удается? Если для размещения объекта нет памяти, часто бывает очень мало, что можно сделать в этом процессе.

Ответ 4

Вам по-прежнему необходимо проверить наличие сбоя в распределении памяти.

Либо

scoped_array<char> buf;

try {
  buf.reset( new char[MAX_BUF] );
} catch( std::bad_alloc& ) {
  // Handle the failure
}

или

scoped_array<char> buf( new(std::nothrow)char[MAX_BUF] );

if( buf.get() == NULL ) {
   // Handle the failure
}