Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.08.2009, 17:38   #1
Troi666
Пользователь
 
Регистрация: 01.12.2008
Сообщений: 58
По умолчанию (C++) bad_alloc (подавление/обход)

Здравствуйте! Снова возникло желание подавить исключение bad_alloc (возникает при запросе блока динамической памяти, если свободного блока такого размера нет). В общем привожу 3 варианта кода. 1-й рабочий - остальные нет. Вот хотелось бы узнать...почему?

Код1 (рабочий)
Код:
#include <iostream>
#include <conio>
#include <vcl>
using namespace std;

const long MaxStr=100000, MaxStb=100000;

void BadMem()
{
   cout<<"Mem lost";
   getch();
   exit(1);
}
void main()
{
   set_new_handler(BadMem);
   long ** EatOfMem = new long * [MaxStr];
   for (long i=0; i<MaxStr; i++)
   {
         EatOfMem[i] = new long[MaxStb];
         cout<<"IT: "<<i+1<<"\n";
   }
   getch();
}
Код 2 (не пашет)
Код:
#include <iostream>
#include <conio>
#include <vcl>
using namespace std;

const long MaxStr=100000, MaxStb=100000;

void main()
{
   set_new_handler(0);
   long ** EatOfMem = new long * [MaxStr];
   for (long i=0; i<MaxStr; i++)
         if ((EatOfMem[i] = new long[MaxStb])!=0)
               cout<<"IT: "<<i+1<<"\n";
         else
         {
               cout<<"Mem lost";
               getch();
               exit(1);
         }
}
3 код (не пашет)
Код:
#include <iostream>
#include <conio>
#include <vcl>
using namespace std;

const long MaxStr=100000, MaxStb=100000;

void main()
{
     long ** EatOfMem = new long * [MaxStr];
     for (long i=0; i<MaxStr; i++)
     {
          try
          {
               EatOfMem[i] = new long[MaxStb];
          }
          catch(std::bad_alloc)
          {
               cout<<"Mem lost";
               getch();
               exit(1);
          }
          cout<<"IT: "<<i+1<<"\n";
     }
}
Troi666 вне форума Ответить с цитированием
Старый 11.08.2009, 19:03   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,089
По умолчанию

Предположения следующие:
2) set_new_handler(0) возвращает стандартное поведение на ошибку оператора new, а не делает так, что экзепшен не валится. В данном случае от этой строки, как я понимаю, ничего не меняется. Для этого, кажется, существует параметр nothrow для оператора new, т.е. надо выделять память так: "new (nothrow) ..."
3) попробуйте написать так: catch(std::bad_alloc&) предполагаю, что нет места для создания копии выкинутого bad_alloc'a
pu4koff вне форума Ответить с цитированием
Старый 11.08.2009, 19:22   #3
Troi666
Пользователь
 
Регистрация: 01.12.2008
Сообщений: 58
По умолчанию

Так... код №2 заработал с изменениями. 3-й пока работать не хочет..
Смущает одно: прикрепил скриншот страницы книжки Архангельского...судя по ней всё правильно..даже правильно во втором коде без изменений...
Код:
#include <iostream>
#include <conio>
#include <vcl>
#include <new>
using namespace std;

const long MaxStr=100000, MaxStb=100000;

void main()
{
   long ** EatOfMem = new long * [MaxStr];
   for (long i=0; i<MaxStr; i++)
         if ((EatOfMem[i] = new(nothrow) long[MaxStb])!=0)
               cout<<"IT: "<<i+1<<"\n";
         else
         {
               cout<<"Mem lost";
               getch();
               exit(1);
         }
}
Изображения
Тип файла: jpg 2009-08-11_192517.jpg (81.7 Кб, 126 просмотров)

Последний раз редактировалось Troi666; 11.08.2009 в 19:27.
Troi666 вне форума Ответить с цитированием
Старый 11.08.2009, 19:56   #4
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,089
По умолчанию

Возможно проблема из-за различия версий вышего компилятора и компилятора автора книги. Builder изначально слабо поддерживал стандарт С++ и много там внесено "отсебятины", но постепенно он движется к истинному С++, а потому поведение некоторых функций могло измениться. Кроме того, стандарт С++ тоже не стоит на месте и то, что было правильно 5 лет назад, может быть неправильно сейчас.
3-й пример у меня отработал нормально в MS VC++ 2008 и в вашем и в моём варианте, но всёже предпочтительнее ловить ссылку, а то куска памяти под дополнительный bad_alloc может не оказаться. Стандарт языка гарантирует наличие памяти только под один bad_alloc, а остальное уже - особенности конкретного компилятора.
Посмотрите еще по F1 что на счет bad_alloc и set_new_handler написано. Может там примерчики подходящие будут именно для вашего компилятора.
pu4koff вне форума Ответить с цитированием
Старый 11.08.2009, 20:07   #5
Troi666
Пользователь
 
Регистрация: 01.12.2008
Сообщений: 58
По умолчанию

Спасибо! Но тем не менее всё пока остаётся достаточно странным... Вот что удалось по set_new_handler отрыть To retain the traditional version of new, which does not throw exceptions, you can use set_new_handler(0). Как я понимаю эксепшны генерироваться не должны, однако ж генерятся) По bad_alloc информацию в справке пока найти не удалось..странно.. Насчёт 3-го примера: у меня эксепшн даже по ссылке не ловится...даже в catch мы не попадаем... bad_alloc лезет на строчке с выделением памяти...
Troi666 вне форума Ответить с цитированием
Старый 11.08.2009, 20:29   #6
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,089
По умолчанию

Delphi по умолчанию перехватывает все исключения вне зависимости от наличия блока try. Может билдер так же поступает. Попробуйте запустить exe через проводник, а не из среды.
A с set_new_handler вообще непонятки какие-то. Везьде пишут, что set_new_handler(0) возвращает стандартное поведение, но в некоторых местах с оговоркой, что не бросаются исключения.
Если рассуждать логически: set_new_handler возвращает указатель на предыдущий обработчик исключения и в первый раз возвращает ноль, т.е. стандартное поведение идёт при указателе на обработчик равном нулю. Таким образом, мы пытаемся ноль поменять на ноль, т.е. смысла никакого в данном случае вроде как и нет. Ну а если стандартное поведение бросает исключения, то и после set_new_handler(0) исключения бросаться будут.
В общем, по логике вещей тут "which does not throw exceptions" лишнее, а иначе просто к стандартному поведению никак не вернемся.

Последний раз редактировалось pu4koff; 11.08.2009 в 20:43.
pu4koff вне форума Ответить с цитированием
Старый 13.08.2009, 21:58   #7
Troi666
Пользователь
 
Регистрация: 01.12.2008
Сообщений: 58
По умолчанию

Огромное спасибо! Код 3 из проводника запустился и выполнился без проблем и в вашем и моём случаях! Похоже билдер действительно ловит всё, что захочет самостоятельно
Troi666 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подавление запросов системы безопасности Outlook2003 eva_yk Общие вопросы .NET 0 28.07.2009 03:13
Обход Н/Д Slavik Microsoft Office Excel 2 09.05.2009 00:49
С++|bad_alloc|Заполнение оперативной памяти Troi666 Помощь студентам 0 30.04.2009 00:15
Подавление перехода по ссылке, не должно происходить событие Elfer JavaScript, Ajax 2 31.08.2008 19:50
обход дерева ribka Помощь студентам 2 11.12.2007 20:38