Поиск:

Ответ в темуСоздание новой темы Создание опроса
> странный вылет программы 
:(
    Опции темы
stmamont
Дата 10.1.2007, 02:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 343
Регистрация: 13.3.2004
Где: влг

Репутация: 3
Всего: 3



Возможно глупый вопрос, но ума не приложу куда смотреть!

Программа выполняет долгую работу, (несколько суток).
И вот на 5 часу работы она странно завершила работу.
т.е. не выдала никакой ошибки , ничего, просто завершилась.
Приложение многооконное, программа выключается при закрытии всех окон.
Я с ней ничего не делал.
за памятью следил (в списке процессов смотрел сколько памяти ест, на момент закрытия было порядка 20 Мб).
Компьютер мощный.
ПО-моему, ошибка во всяком случае должна была выскочить.
Не подскажете что могло произойти?


--------------------
user posted image
PM MAIL ICQ   Вверх
dumb
Дата 10.1.2007, 05:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



посмотри в EventLog. в серверных виндах галка "уведомлять о сбоях" снята по умолчанию, так что падающее приложение только пишет в лог "ватсона" и в EventLog.

если нет, то вставляй подробный логгинг, отлаживайся.
PM MAIL   Вверх
stmamont
Дата 10.1.2007, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 343
Регистрация: 13.3.2004
Где: влг

Репутация: 3
Всего: 3



то есть такое возможно? что бы программа закрылась без ошибок? хотя в ней кода даже такого нету. (чтобы закрывалась?)


--------------------
user posted image
PM MAIL ICQ   Вверх
Bima
Дата 10.1.2007, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



В винде свойство такое есть, закрывать зависшие процессы. А насчет твоей программы, здесь не телепаты, что бы судить, правильно у тебя написано программа или нет, может она 5 часов работает, а потом вызывает какую нибудь инструкцию, которая неправильно выделяет память и все - кирдык, винда такого не простит smile.
Что бы знать где программа выскочила, делай логи, то есть после определенных функций или команд пиши время и действие в файл, а потом просматривай логи.


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
stmamont
Дата 11.1.2007, 02:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 343
Регистрация: 13.3.2004
Где: влг

Репутация: 3
Всего: 3



>>может она 5 часов работает, а потом вызывает какую нибудь инструкцию, которая неправильно выделяет память и все - кирдык, винда такого не простит

Очень похоже на это.
работает около 3 часов, перелопатила 5000 элементов.
После чего Access Violation at address 0000000032 . Т.е. я похоже пытался создать объект при помощи new но винда память не выделила, и я без проверки полез к какоу то элементу.

Почему такое может произойти?
На момент ошибки программа весит в оперативке 20Мб. Что вполне адекватно информации которую она хранит, т.е. утечек памяти быть не должно. (В пред версии была утечка, программа вылетела при размере 300Мб))))

Почему система может не выделить память? и занулит ли  она указатель , если не смогла выделить память?


--------------------
user posted image
PM MAIL ICQ   Вверх
dumb
Дата 11.1.2007, 03:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



Цитата(stmamont @  11.1.2007,  02:01 Найти цитируемый пост)
и занулит ли  она указатель , если не смогла выделить память?

единственный вопрос, на который можно ответить. занулит.

Цитата(stmamont @  11.1.2007,  02:01 Найти цитируемый пост)
После чего Access Violation at address 0000000032

чаще всего такое бывает при вызове метода несуществующего объекта.

может помочь - madExcept
PM MAIL   Вверх
Bima
Дата 11.1.2007, 06:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Опять те же грабли.
МЫ здесь не телепаты, что бы обсуждать гипотетический код на предмет ошибки.
Цитата

Т.е. я похоже пытался создать объект при помощи new но винда память не выделила, и я без проверки полез к какоу то элементу

если ты в цикле постоянно создаешь элементы и их удаляешь, то это не есть ГУД. Попробуй их создать при создании формы, а удалять в конце программы. Конечно я предвижу вопрос, что всякое может понадобиться в момент исполнения программы, и программа должна все выполнить, но  создание элементов  с помощью new не дает гарантии, что он создался ( если быть точне я не помню, как проверить создание данного элемента), в отличии от "сишного"  оператора выделения памяти (типа allocmem) у которого можно проверить выделилась память или нет. Для примера код:
Код

unsigned int memory(unsigned int Size)  // Функция выделения памяти
    {
          int                   stat;     // Флаг успушного выделения памяти
          unsigned long          max;     // Переменная мах данных по ПДП
          unsigned long           Ch=1;         // Счетчик параграфов памяти
          unsigned int          temp;     // Временный буфер для массива
          stat=allocmem(Size,&adres_buf); // Выделение памяти
          if (stat!=-1)                   // Проверка выделения памяти
                {
                printf ("Out of memory\n");
                exit(0);
                }
          addr = ((unsigned long)adres_buf << 4); // Вычисление линейного адреса
          max = 0xffff+0x1 - ((addr>>1) & 0xffff);// Вычесляем и проверяем сколько
          if (max>512)                         // данных может передать ПДП в пре-
                {                                // делах одной страницы памяти
                return 0;  // Если до конца страницы больше 512 слов то выходим
                }
          else           // иначе выделяем временный участок памяти, размером рав-
                {          // ным на один параграф больше чем предыдущее выделение
                Ch=1;      // памяти и после этого выделяем нужный участок памяти
                met1:
                freemem(adres_buf);
                printf("\a");
                stat=allocmem((int)max/16,&temp);
                if (stat!=-1)
                    {
                    printf ("Out of memory\n");
                    exit(0);
                    }
                stat=allocmem(Size,&adres_buf);
                if (stat!=-1)
                    {
                    printf ("Out of memory\n");
                    exit(0);
                    }
                addr = ((unsigned long)adres_buf << 4);
                max = 0xffff+0x1 - ((addr>>1) & 0xffff);
                if (max>512)
                    {
                    freemem(temp);
                    return 0;
                    }
                Ch++;              // если выделение памяти не прошло успешно
                max=max+Ch;        // то инкремируем счетчик параграфов и повторяем
                freemem(temp);     // процедуру выделения памяти снова
                goto met1;
                }
     }

Я взял подпрограмму для выделения памяти, которую писал лет 5 назад. Сам алгоритм не важен, а важно, как идет выделение памяти и проверка выделения памяти. Анологично должно быть и в твоей программе.


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Anikmar
Дата 11.1.2007, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Цитата(Bima @  11.1.2007,  06:56 Найти цитируемый пост)
но  создание элементов  с помощью new не дает гарантии, что он создался ( если быть точне я не помню, как проверить создание данного элемента), в отличии от "сишного"  оператора выделения памяти (типа allocmem) у которого можно проверить выделилась память или нет.


Почему нельзя проверить? 

Вот что пишет тот же HELP Buildera:
Цитата

The new operators offer dynamic storage allocation, similar but superior to the standard library function malloc. These allocation functions attempt to allocate size bytes of storage. If successful, new returns a pointer to the allocated memory. If the allocation fails, the new operator will call the new_handler function. The default behavior of new_handler is to throw an exception of type bad_alloc. If you do not want an exception to be thrown, use the nothrow version of operator new.  The nothrow versions return a null pointer result on failure, instead of throwing an exception.


По умолчанию, при ошибки выделении памяти new вылетает исключение
Если использовать форму new(nothrow) - то исключения не будет, а при ошибке вернет NULL

Кстати: я точно не проверял, но по-моему Builder по умолчанию делает как раз nothrow - т.е. без исключения, но я точно не помню.
PM MAIL ICQ   Вверх
Vyacheslav
Дата 11.1.2007, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Anikmar @  11.1.2007,  11:23 Найти цитируемый пост)
Кстати: я точно не проверял, но по-моему Builder по умолчанию делает как раз nothrow - т.е. без исключения, но я точно не помню. 

Bulder придерживается стандарта и соответсвенно форма new при ошибке выделения памяти генерит исключение. Ладно я,  еще успел поработать на компиляторах "достандартной" эпохи, но сейчас то ....  Тем не менее на собеседовании при приеме на работу 50 процетов кандидатов не видят в ниже следующем коде ничего криминального
Код

char* pchar = new char[size];
if (!pchar) {
//ERROR
}
 
Более того. Когда явно указываешь им на бессмысленность проверки, уверяют что ВСЕ И ВСЕГДА  ТАК ДЕЛАЮТ.

Добавлено @ 11:47 
Цитата(stmamont @  11.1.2007,  02:01 Найти цитируемый пост)
Т.е. я похоже пытался создать объект при помощи new но винда память не выделила, и я без проверки полез к какоу то элементу.

Этого не может быть, потому что быть не может. Если конечно Вы не промаскировали возникшее при этом исключение. Скорее всего, Вы обратили к объекту, который уже уничтожили или еще не создали


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
stmamont
Дата 11.1.2007, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 343
Регистрация: 13.3.2004
Где: влг

Репутация: 3
Всего: 3



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


--------------------
user posted image
PM MAIL ICQ   Вверх
Bima
Дата 11.1.2007, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Vyacheslav поясни свой код:
Код

char* pchar = new char[size];
if (!pchar) {
//ERROR
}

Насколько я понимаю, здесь выделяется массив размерностью size и указатель pchar указывает на этот массив. Всегда не в ладах был с этими указателями, поэтому хочу поточнее уловить этот момент. Я не знаю, что возвращает в данном случае операция new char[size], но по логике эта операция может вернуть адрес на первый элемент массива и он не будет равен 0. Или я не прав???


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
stmamont
Дата 11.1.2007, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 343
Регистрация: 13.3.2004
Где: влг

Репутация: 3
Всего: 3



смысл такой: оператор new выкидывает exception если система не смогла выделить память. И соответственно до второй строчки работа программы не дойдет.
А в если все пройдет нормально, то оператор new вернет указатель на первый элемент массива char размера size и проверка тем более не нужна.


--------------------
user posted image
PM MAIL ICQ   Вверх
Vyacheslav
Дата 11.1.2007, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Bima @  11.1.2007,  13:48 Найти цитируемый пост)
Vyacheslav поясни свой код:


stmamont прекрасно все разъяснил без меня smile


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 11.1.2007, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



теперь понял, спасибо


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Sfairet
Дата 11.1.2007, 17:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 11.1.2007

Репутация: нет
Всего: нет



По моему вариант с нулём не такой уж и безнадежный, во первых старые версии new возвращают именно 0 (до принятия стандарта), к томуже не каждый компилятор согласиться генерировать исключение bad_alloc, а также просто будет использовать вариант с 0
PM MAIL   Вверх
Vyacheslav
Дата 11.1.2007, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Sfairet @  11.1.2007,  17:20 Найти цитируемый пост)
к томуже не каждый компилятор согласиться генерировать исключение bad_alloc, а также просто будет использовать вариант с 0 

Это как это? И кто его , компилятор, спрашивать будет? smile 
А вариант, уверяю Вас, безнадежный. Особенно, при собеседовании при преме на работу smile



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Sfairet
Дата 11.1.2007, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 11.1.2007

Репутация: нет
Всего: нет



Имелись ввиду компиляторы не совместимые со стандартом=)

Да я и не спорю что вариант с нулём большая редкость, но тем не менее при определенных обстаятельствах он не исключён=)
PM MAIL   Вверх
Bima
Дата 12.1.2007, 07:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Sfairet  и Vyacheslav  скажите, а будет ли работать такой код???
Код

try{
     char* pchar = new char[size];
     }
catch(...)  
      {
      //Error
      } 



--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
stmamont
Дата 12.1.2007, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 343
Регистрация: 13.3.2004
Где: влг

Репутация: 3
Всего: 3



Bima, вот к этому и велось)
именно так и нужно отлавливать ошибку


--------------------
user posted image
PM MAIL ICQ   Вверх
Vyacheslav
Дата 12.1.2007, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Вот так 
Код

catch(...)  
      {
      //Error
      } 

все таки не стоит.  Лучше по-аккуратнее
Код

catch(std::bad_alloc ex)  
 {
      //Error
 } 


или хотя бы так
Код

catch(std::exception& ex)  
 {
      //Error
 } 





--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 16.1.2007, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



набрал у себя в программе при создании потока следущее:
Код

try
  {
  TMethread *thr1 = new TMethread(true);
  }
catch(std::exception ex)  
 {
      //Error
 } 


по сути дела, то же самое, но у меня ругается на строку:
catch(std::exception ex)

Что не так, где подвох???


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
pandrew
Дата 16.1.2007, 10:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 213
Регистрация: 27.3.2006

Репутация: 3
Всего: 3



Добавь #include <except.h>
Кроме того thr1 не будет видно вне скобок. Едва ли ты это хотел.
PM MAIL   Вверх
Bima
Дата 16.1.2007, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Цитата

Добавь #include <except.h>

Заработало. Vyacheslav  писал, что лучше использовать:
Код

catch(std::bad_alloc ex)  
 {
      //Error
 } 

Для создания потоков с помощью new это тоже применимо, или есть std, какой нибудь другой???

Цитата

Кроме того thr1 не будет видно вне скобок. Едва ли ты это хотел. 

что значит не будет видно???
Я его создал в скобках, он отработал и убился. Приостанавливать и завершать экстренно мне его не нужно.


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
stmamont
Дата 16.1.2007, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 343
Регистрация: 13.3.2004
Где: влг

Репутация: 3
Всего: 3



если обобщить
Код

#include <except.h>

...

TMethread *thr1;
try
  {
  thr1 = new TMethread(true);
  }
catch(std::exception ex)  
 {
      //Error
 } 



--------------------
user posted image
PM MAIL ICQ   Вверх
Vyacheslav
Дата 16.1.2007, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Код

#include <exception>

Это во-первых.
Во-вторых, если Вы используете VCL, его разработчики как правило перехватывают первоначальные исключения и вместо них генерят свои с типом Exception. Так что, Ваш код должен выглядеть примерно так
Код

try
  {
  TMethread *thr1 = new TMethread(true);
  }
catch(Exception* ex)  
 {
      //Error
 } 

В-третьих, абослютно не вижу смысла ловить исключения по месту. По месту стоит ловить их тогда, когда есть возможность что-то исправить. Здесь же ясно, что объект не создался(неважно по какой причине) и программу либо следует прекратить полностью, либо прекратить выполнение конкретного участка  с выдачей информации.  По этому я бы здесь исключение не ловил. А все сделал централизованно
Вообще любая программа должна начинаться с организации обработки ошибок.
Слава богу, разработчики VCL продумали это за нас. И я обычно делаю так.
1. Выкладываю ApplicationEvents, который использую для централизовааной обработки всех действий
2. Задаю обработчик исключений типа
Код

void __fastcall TMainDataModule::ApplicationEventsException(
      TObject *a_Sender, Exception *a_Exc)
{
// Если это клиентское исключение, то просто выдаем сообщение...
    try
    {
        if (EipException* Exc = dynamic_cast<EipException*>(a_Exc))
        {
            Exc->Show();
            return;
        }
        // Если это серьезная ошибка
        std::auto_ptr<TErrorDialog> Dlg(new TErrorDialog(this, a_Exc,a_Sender));
        Dlg->ShowModal();
        // если ошибка произошла при входе в систему,
        // прекращаем работу
        if (m_Logining)
            Application->Terminate();
    }
    catch(...)
    {
    }
}

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

/////////////////////////////////////////////////////////////////////////////
// ## Назначение: Собственный класс исключения
// ## Описание :  В Message содержится код сообщения
class PACKAGE EipException: public Exception
{
private:
    bool m_NotCode;
    TVarRec* m_Args;
    int m_Size;
    TMsgDlgType  m_DlgType;
public:
#pragma option push -w-inl
    __fastcall EipException(AnsiString a_Msg):Exception(a_Msg){};
    __fastcall EipException(AnsiString a_Msg, TMsgDlgType a_DlgType)
                            :Exception(a_Msg),
                             m_NotCode(true),
                             m_DlgType( a_DlgType){};
#pragma option pop
    __fastcall EipException(AnsiString, const System::TVarRec*, const int);
    void __fastcall Show(void);
    __fastcall ~EipException(void);
};

Ну и вся обработка в самом коде сводится к
1.Сами генерим исключение
Код

TAdsConnection* __fastcall TPluginModule::GetMainConnection()
{
    if (!ComponentState.Contains(csDesigning))
    {
       static TAdsConnection* Connection = dynamic_cast<TAdsConnection*>(
            Screen->DataModules[0]->FindComponent(cMainConnection));
        if (!Connection)
            throw Exception(Format("AdsConnection '%s' не найден",
                                    ARRAYOFCONST((cMainConnection))));
        return Connection;
    }
    return NULL;
}

2.Подменяем первоначалые на свои
Код

bool __fastcall TMainDataModule::Login(TObject*         a_Sender,
                                       const AnsiString& a_User,
                                       const AnsiString& a_Password,
                                       const AnsiString& a_Database)
{
    try
    {

        MainConnection->ConnectPath  =
                           IncludeTrailingPathDelimiter(a_Database)
                         + cDictionaryName;
        MainConnection->Username = a_User;
        MainConnection->Password = a_Password;
        MainConnection->IsConnected = true;
    }
    catch(EADSDatabaseError* Exc)
    {
        switch (Exc->ACEErrorCode)
        {
          case AE_FILE_NOT_FOUND:
              throw EipException(NotFoundDictionary
                               + QuotedStr(a_Database),mtError);
          case 7078:
              throw EipException(NotUserAuthenticate,mtError);
          default:
              throw;
        }
    }
    return true;
}

 






--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Лена
Дата 16.1.2007, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 879
Регистрация: 16.8.2006

Репутация: 11
Всего: 11



>смысл такой: оператор new выкидывает exception если система не смогла выделить память.

Значит в книге Архангельского ошибка? Там сказано, что просто вернется NULL, в случае не возможности выделить память через new.
PM MAIL   Вверх
Vyacheslav
Дата 16.1.2007, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Лена @  16.1.2007,  12:22 Найти цитируемый пост)
Значит в книге Архангельского ошибка? Там сказано, что просто вернется NULL, в случае не возможности выделить память через new

Архангельского надо читатать с осторожностью smile



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
mrbrooks
Дата 16.1.2007, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



Цитата(Vyacheslav @ 16.1.2007,  13:01)

Архангельского надо читатать с осторожностью smile

Это почему. Не ужели автор допускает такие ошибки? Это конечно не в тему. Заранее пардон.
PM MAIL   Вверх
Anikmar
Дата 16.1.2007, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



И у Архангельского и в стандартном HELPе ошибки есть.
Нет в мире ничего совершенного.  smile 
PM MAIL ICQ   Вверх
Vyacheslav
Дата 16.1.2007, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(mrbrooks @  16.1.2007,  14:43 Найти цитируемый пост)
Это почему. Не ужели автор допускает такие ошибки? Это конечно не в тему. Заранее пардон. 

Потому что, для Архангельского - главное объем.  Правда такие ошибки - верх некомпетентности. В конце концов если не со стандартом, то хотя бы с хелпом следовало ознакомиться повнимательнее
Цитата( C++Builder Help)

Category

Operators, C++-Specific Keywords

Syntax

void *operator new(std::size_t size) throw(std::bad_alloc);

void *operator new(std::size_t size, const std::nothrow_t &) throw();
void *operator new[](std::size_t size) throw(std::bad_alloc);
void *operator new[](std::size_t size, const std::nothrow_t &) throw();
void *operator new(std::size_t size, void *ptr) throw();    // Placement form

void *operator new[](std::size_t size, void *ptr) throw();  // Placement form

Description

The new operators offer dynamic storage allocation, similar but superior to the standard library function malloc. These allocation functions attempt to allocate size bytes of storage. If successful, new returns a pointer to the allocated memory. If the allocation fails, the new operator will call the new_handler function. The default behavior of new_handler is to throw an exception of type bad_alloc. If you do not want an exception to be thrown, use the nothrow version of operator new.  The nothrow versions return a null pointer result on failure, instead of throwing an exception.
The default placement forms of operator new are reserved and cannot be redefined. You can, however, overload the placement form with a different signature (i.e. one having a different number, or different type of arguments). The default placement forms accept a pointer of type void, and perform no action other than to return that pointer, unchanged. This can be useful when you want to allocate an object at a known address. Using the placement form of new can be tricky, as you must remember to explicitly call the destructor for your object, and then free the pre-allocated memory buffer. Do not call the delete operator on an object allocated with the placement new operator.

A request for non-array allocation uses the appropriate operator new() function. Any request for array allocation will call the appropriate operator new[]() function. Remember to use the array form of operator delete[](), when deallocating an array created with operator new[]().

Note:    Arrays of classes require that a default constructor be defined in the class.

A request for allocation of 0 bytes returns a non-null pointer. Repeated requests for zero-size allocations return distinct, non-null pointers.

Только вот эта форма буде возвращать NULL
Код

void *operator new(std::size_t size, const std::nothrow_t &) throw();
void *operator new[](std::size_t size, const std::nothrow_t &) throw();

Обычные  генерят exception



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Anikmar
Дата 16.1.2007, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Да ладно нападать на Архангельского. Не одна сотня программистов по его книгам начинала. Хотя конечно указанный прокол достаточно серьезный, но в общем понимании его книги очень и очень полезны.
PM MAIL ICQ   Вверх
Vyacheslav
Дата 16.1.2007, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Anikmar @  16.1.2007,  15:03 Найти цитируемый пост)
 Не одна сотня программистов по его книгам начинала.

Вот-вот. А я то думаю, и чего это 50% кандидатов при собеседовании чуть до мигрени меня не доводят, убеждая, что new просто объязан возвращать NULL.  smile



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Anikmar
Дата 16.1.2007, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Vyacheslav, я не думаю, что это должен быть основной критерий отбора. Даже если кандидат в этом ошибается, это вовсе не значит, что он и в остальном полный 0.
Люди они разные, а программисты тем более  smile 
PM MAIL ICQ   Вверх
Vyacheslav
Дата 16.1.2007, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Anikmar @  16.1.2007,  15:16 Найти цитируемый пост)
Даже если кандидат в этом ошибается, это вовсе не значит, что он и в остальном полный 0.

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




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Anikmar
Дата 16.1.2007, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Цитата(Vyacheslav @  16.1.2007,  15:36 Найти цитируемый пост)
Это означает, что человек  вообще не писал серьезных приложений


К стыду своему признаюсь, что я почти нигде не перехватыфваю это исключение. Если не сработал new - происходит отработка на уровне Application - т.к. в 99% случаев это говорит о том, что дальше работать нельзя. За исключением соучаев, когда в какой-нибудь ветке требуются уж очень большие ресурсы, на которые реально может нехватить памяти.

Если вылетает new с объектом размером 100 байт - значит где-то очень серьезная утечка. А заключать каждый new в блок try catch приведет уж к больно большому разрастанию кода.

Правда я себя не считаю профессионалом - скорее плотный любитель.
PM MAIL ICQ   Вверх
Vyacheslav
Дата 16.1.2007, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Anikmar @  16.1.2007,  15:43 Найти цитируемый пост)
К стыду своему признаюсь, что я почти нигде не перехватыфваю это исключение. Если не сработал new - происходит отработка на уровне Application - т.к. в 99% случаев это говорит о том, что дальше работать нельзя.

Угу. Потому что за Вас это делает VCL 

Код

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    try
    {
         Application->Initialize();
         Application->CreateForm(__classid(TForm1), &Form1);
         Application->Run();
    }
    catch (Exception &exception)
    {
         Application->ShowException(&exception);
    }
    catch (...)
    {
         try
         {
             throw Exception("");
         }
         catch (Exception &exception)
         {
             Application->ShowException(&exception);
         }
    }
    return 0;
}
/


Цитата(Anikmar @  16.1.2007,  15:43 Найти цитируемый пост)
 заключать каждый new в блок try catch приведет уж к больно большому разрастанию кода.

Заключать каждый new в блок try catсh - обратная сторона той же некомпетентности. 
См предыдущий мой пост. Ловить нужно по возможности( подчеркиваю - по возможности) как можно дальше от того места, где исключение  произошло. Но ловить обязательно. Вам ведь не не нравится, когда  Windows выходит на синий экран. Так и  с  программой. Сработала или не сработала правильно программа, но в 95 процентах пользователь должен решать, хочет или нет он прекратить с ней работу. А для этого нужно очень аккуратно работать с исключениями   



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Anikmar
Дата 16.1.2007, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Цитата(Vyacheslav @  16.1.2007,  16:07 Найти цитируемый пост)
Сработала или не сработала правильно программа, но в 95 процентах пользователь должен решать, хочет или нет он прекратить с ней работу.


Согласен с этим на 100%

Но после этого обсуждения я начинаю себя ощущать менее компетентным   smile  

Хотя максимум усилий я прилагаю к повышению дуракоустойчивости программы, и уж конечно, указанный блок в функции Winmain у меня переделан и выдает сообщение по-русски.
PM MAIL ICQ   Вверх
Bima
Дата 16.1.2007, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Vyacheslav, я пытался разобрать ваш пример по "полочкам", не вышло. Скорее всего знаний не хватает, или данных.
Вы не могли бы сделать простой пример (там ловятся централизовано исключения), где скажем так, выделяется память, математические операции(сложение делние без проверки на 0) и что нибудь еще. По возможности с коментариями и выложить этот пример здесь, на всеобщее обучение.
Чем проще пример будет, тем легче его будет понять.

Я всегда ловил исключения только "местно", но это пошло еще с программ DOS-их. Сейчас хочу отойти от этой привычки (можно сказать, вы убедили меня в этом).

P.S. кстати ВСВ тоже учил по Архангельскому, потому, что на тот момент, эта была единственная книжка, которую я нашел (инета небыло).


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Anikmar
Дата 16.1.2007, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Выскажу еще свое мнение по поводу централизованного перехвата исключений.

В большинстве своем они нужны для отладки и для корректного сохранения данных. Ну ни как пользователю не поможет сообщение хоть по-русски хоть по-французски "Произошло деление на 0. Приложение будет закрыто".

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

Хотя VCL страдает избыточной любовью к исключениям, взять функции типа atoi - зачем генерить исключения в них лично мне не понятно, и там, естественно появляется обработчик с идиотской надписью"Вы ввели не число. Введите, пожалуйста число!"


PM MAIL ICQ   Вверх
Vyacheslav
Дата 16.1.2007, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Anikmar @  16.1.2007,  16:53 Найти цитируемый пост)
В большинстве своем они нужны для отладки и для корректного сохранения данных. Ну ни как пользователю не поможет сообщение хоть по-русски хоть по-французски "Произошло деление на 0. Приложение будет закрыто".

Угу. Человек работал со складом. Не вышло. Он сообшил об ошибке администратору и чтобы продолжить работу с други модулем этой же программы, получает сообщение "Приложение будет закрыто"
Еще раз. У Вас Windows наверняка иногда выдает ошибки.  И что после этого оно перегружается?



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Anikmar
Дата 16.1.2007, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



Цитата(Anikmar @  16.1.2007,  16:53 Найти цитируемый пост)
Перехватывать исключения нужно обязательно, но желательно в тех местах, откуда по возможности можно продолжить исполнение кода, пусть и с урезанным функционалом, типа "Извините, в программе произошла ошибка, данная функция недоступна, сообщите разработчику".

Именно про такие случаи я и писал. Максимально сохранить возможность продолжать работу. Что зачастую невозможно при очень далеких перехватах исключения. Чем дальше тем лучше, конечно, но и перегибать не надо.
PM MAIL ICQ   Вверх
Vyacheslav
Дата 16.1.2007, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Anikmar @  16.1.2007,  16:53 Найти цитируемый пост)
взять функции типа atoi - зачем генерить исключения в них лично мне не понятно, и там, естественно появляется обработчик с идиотской надписью"Вы ввели не число. Введите, пожалуйста число!"

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

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  //ошибка кодирования  
  try {
        int temp = AnsiString("ddddd").ToInt();
    } catch(Exception* exp)
    {
        throw Exception(exp->Message);
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ApplicationEvents1Exception(TObject *Sender,
      Exception *E)
{
       if (dynamic_cast< EConvertError* >(E)) {
            ShowMessage("Ошибка конвертации. Вы неправильно ввели число. Повторите ввод");
       return;
       }
       if (Application->MessageBox(Format("Программа выполнила недопустимую операцию: %s  в файле : %s в строке :%s"
                                      "Завершить программу?", ARRAYOFCONST(( E->Message, String(__throwFileName), String(__throwLineNumber) ))).c_str(),
                                      "Ошибка", MB_YESNO ) == IDYES    ) {
       Close();
       }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
//ошибка ввода 
int temp1 = Edit1->Text.ToInt();
 int temp2 = Edit3->Text.ToInt();
}
//---------------------------------------------------------------------------


Прошу обратить внимание на следующий факт. Там где ошибка связана с неправаильным вводом(Button2Click), будет выдано сообщение. Причем абсолютно неважно, где был выброшено исключение. В данном пример две строчки в Button2Click . А их может быть 100, но программа поведет себя одинаково.
А вот в Button1Click предположим  эта же ошибка  конвертации тоже возможна, но связана она не с вводом, а ошибкой в коде.  Что я , как программист предпринимаю?  Зная, что все причины , вызывающие исключения в этом коде не могут быть исправлены действиями пользователя, я их перехватываю и дальше посылаю свое. Программа поведет себя по другому. Она выведет ошибку , причем с именем файла и строки, где произошло исключение и спросит нужно ли завершить программу. Здесь, конечно, все немного утрировано, но смысл , я надеюсь, понятен.

Добавлено @ 17:52 
Цитата(Anikmar @  16.1.2007,  17:04 Найти цитируемый пост)
Что зачастую невозможно при очень далеких перехватах исключения. 

Ошибаетесь. Как раз возможно smile
В моем предыдущем примере поставте сколько угодно кнопок, в из обработчиках сгенерите исключения и давите как Вам вздумается. Уверяю Вас, программа завершится только с Вашего разрешения. Причем, что удивительно, я  каждое исключение не обрабатываю


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Anikmar
Дата 16.1.2007, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 34
Всего: 59



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

Век живи - век учись.


PM MAIL ICQ   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.1008 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.