Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

TRegistry

20K
10 ноября 2006 года
Flenger
3 / / 01.11.2006
при нажатии на кнопку

void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRegistry* regKey;
regKey->RootKey=HKEY_LOCAL_MACHINE;
regKey->OpenKey("\\Software\\A Projects",true);


}

выбивает сообщение
Access violation at adress 40048416 in module rtl60.bpl.Read of address 0000002D

Почему....?????
309
10 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
Всё правильно, объявляешь указатель на объект, а где код создания объекта???????????????????????????????????????????????
Скажите честно, вы про операторы new и delete хоть что-нибудь слышали?
Давайте, угадаю с трёх раз: нет :D
20K
10 ноября 2006 года
kossak
20 / / 10.11.2006
Перепиши так:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRegistry* regKey = new Registry();
regKey->RootKey=HKEY_LOCAL_MACHINE;
regKey->OpenKey("Software\\A Projects",true);
}

да, не забудь закрыть ключ

Reg->CloseKey();

и освободить память
delete Reg;
delete
294
10 ноября 2006 года
Plisteron
982 / / 29.08.2003
[QUOTE=kossak]Перепиши так:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRegistry* regKey = new Registry();
regKey->RootKey=HKEY_LOCAL_MACHINE;
regKey->OpenKey("Software\\A Projects",true);
}

да, не забудь закрыть ключ

Reg->CloseKey();

и освободить память
delete Reg;
delete[/QUOTE]

И обработать исключения. Ведь гарантии выполнения new Registry() нет, хотя на практике эксепшна на этом месте я ещё не встречал.
309
10 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Plisteron]И обработать исключения. Ведь гарантии выполнения new Registry() нет, хотя на практике эксепшна на этом месте я ещё не встречал.[/QUOTE]
Обрабатывать в начале метода исключение не нужно.
В этом случае его обработка произойдёт внутри объекта Application
20K
11 ноября 2006 года
Flenger
3 / / 01.11.2006
Сенкс!!!!
Про new, delete как раз и слышал но давно ими не пользовался(разве при создании собственных классов когда учил чистый С++), а Builder учу недавно вот потому и протупил......

помоему(недавно вспомнил) более елегантно будет так

TRegistry& regKey = *new Registry();
309
11 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
 
Код:
TRegistry& regKey = *new Registry();

Без обид, но это стилистический бред, вызванный неприятием оператора "->".
Для объектов, которые создаются и удаляются вручную, используются указатели (*).
294
11 ноября 2006 года
Plisteron
982 / / 29.08.2003
[QUOTE=el scorpio]Обрабатывать в начале метода исключение не нужно.
В этом случае его обработка произойдёт внутри объекта Application[/QUOTE]
Ага, и мы вываливаемся из нашей функции, не закрыв файлов, не освободив память, не сохранив результаты вычислений, не записав сообщение об ошибке в лог.
309
12 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Plisteron]Ага, и мы вываливаемся из нашей функции, не закрыв файлов, не освободив память, не сохранив результаты вычислений, не записав сообщение об ошибке в лог.[/QUOTE]
1. Открытие/закрытие файлов лучше сделать а) глобально, записывая хендл как поле формы; б) локализованно, внутри гарантированно рабочего кода
2. Для автоматического освобождения памяти можно использовать стандартный билдеровский контейнер sPointer <T>, и забить на delete :D
3. Уж если такие ошибки начинаются, по про результаты можно забыть
4. А для лога проще один раз написать обработчик, и прицепить его на событие Application->OnException

И вообще, я говорил про частный случай, когда нет нужды лишний раз писать try|catch
294
14 ноября 2006 года
Plisteron
982 / / 29.08.2003
[QUOTE=el scorpio]1. Открытие/закрытие файлов лучше сделать а) глобально, записывая хендл как поле формы; б) локализованно, внутри гарантированно рабочего кода[/QUOTE]
try{} __finally{} чем не гарантированно работающий код?
[QUOTE=el scorpio]3. Уж если такие ошибки начинаются, по про результаты можно забыть[/QUOTE]
Далеко не всегда. Ох как не всегда...

Честно говоря, просто лень дискутировать.
246
14 ноября 2006 года
GIZMO
1.8K / / 30.07.2004
[QUOTE=Plisteron]Ага, и мы вываливаемся из нашей функции, не закрыв файлов, не освободив память, не сохранив результаты вычислений, не записав сообщение об ошибке в лог.[/QUOTE]
согласен...
309
14 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=GIZMO]согласен...[/QUOTE]
И с чем же, интересно, вы соглашаетесь :confused:
1. Если создаётся один объект, то при ошибке его создания, освобождать ничего не нужно. Если больше - то см. sPointer и не майтесь дурью :D
2. Если произошла ошибка в начале функции, значит никаких "результатов" быть не может.
3. Лог ошибок проще сделать один, и присобачить к Application->OnException.
4. Я говорил о конкретном случае.
И вообще. Ошибка "выделения памяти" - это вообще бред. За всю историю работы с Windows, я встречал только одну программу, которая переполняла мне ОЗУ. Речь идёт о "Heroes of M&M 4", которая, я более чем уверен, допускала банальную утечку памяти.
294
15 ноября 2006 года
Plisteron
982 / / 29.08.2003
[QUOTE=el scorpio]2. Если произошла ошибка в начале функции, значит никаких "результатов" быть не может.
3. Лог ошибок проще сделать один, и присобачить к Application->OnException.
4. Я говорил о конкретном случае.
И вообще. Ошибка "выделения памяти" - это вообще бред. За всю историю работы с Windows, я встречал только одну программу, которая переполняла мне ОЗУ. Речь идёт о "Heroes of M&M 4", которая, я более чем уверен, допускала банальную утечку памяти.[/QUOTE]
2. Пример: Проводим сложную обработку данных и перед записью результата в файл хотим сохранить состояние некоторых контролов и позицию окна в файл (для чего нажимаем соотв. кнопку), и вдруг облом... А ты говоришь...
3. Очень часто мне не надо, чтобы все эксепшены обрабатывались в одном месте. Пример из жизни. У меня есть БД, в которую я в разные таблички заливаю всякие хитрые данные. Так вот, экспшны при заливке разных таблиц имеют разные последствия, при некоторых приходится останавливать заливку и подчищать хвосты, а некоторые можно просто проигнорировать и продолжать заливку. Это всё гораздо проще отследить , если иметь несколько блоков try{} catch{}.
4. Сталкивался неоднократно раз, например, при работе с графикой (хотя бы с 180-мегапикселовой картинкой.
309
15 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Plisteron]Проводим сложную обработку данных и перед записью результата в файл хотим сохранить состояние некоторых контролов и позицию окна в файл (для чего нажимаем соотв. кнопку), и вдруг облом... А ты говоришь...
[/QUOTE]

В этом случае, данные всегда останутся доступными, так как они будут хранится в полях формы или же в "фоновом" потоке вычисления. Но локальными для метода-обработчика они быть в описанной ситуации просто не могут.


И вообще, есть такое правило: "не усложнять". :D
Писать try / catch на каждый фрагмент кода - напрасная трата времени и ресурсов.
Подобный код будет оптимальным для данной ситуации, без какого-либо обработчика исключений
 
Код:
void TForm1::Button1Click ()
{
     sPointer <TIniFile> file = new TIniFile (Edit1->Text);
     // здесь мы можем читать/писать файл, а также выполнять команды, способные вызвать ошибку
     // использовать file можно как простой указатель TIniFile*, но удалять его не требуется
}

Именно про это я и говорил
20K
15 ноября 2006 года
kossak
20 / / 10.11.2006
Саласен полностью
294
17 ноября 2006 года
Plisteron
982 / / 29.08.2003
[QUOTE=el scorpio]
 
Код:
void TForm1::Button1Click ()
{
     sPointer <TIniFile> file = [COLOR=RED]new TIniFile (Edit1->Text)[/COLOR];
     // использовать file можно как простой указатель TIniFile*, но удалять его не требуется
}

[/QUOTE]
Удалять-то его не требуется, но речь шла не о том.
Если обломается конструкция, которую я отметил красным (сгенерится исключение при выполнении оператора new), то... см. мой пост про несохранённые данные. Про некоторые неудобства с OnException я тоже писал. Так что от try{} catch{} или try{} __finally {} иногда не уйдёшь. И вообще, по моему скромному мнению, использовать эти конструкции отнюдь не зазорно, главное -- не увлекаться.
309
17 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Plisteron]Удалять-то его не требуется, но речь шла не о том.
Если обломается конструкция, которую я отметил красным (сгенерится исключение при выполнении оператора new), то... см. мой пост про несохранённые данные. Про некоторые неудобства с OnException я тоже писал. Так что от try{} catch{} или try{} __finally {} иногда не уйдёшь. И вообще, по моему скромному мнению, использовать эти конструкции отнюдь не зазорно, главное -- не увлекаться.[/QUOTE]
Скорее всего, обломается не new, а конструктор объекта, из-за того, что ему сунут недопустимое имя файла в виде параметров :rolleyes: .
Что же касается "несохранённых данных", то можно сказать только одно: здесь их нет.
Ибо при исключении, теряются значения только тех объектов, что лежат в стеке внутри обрабатывемой ситуации. В данном случае, try расположен внутри объекта Application, посему "потерять" можно только то, что объявлено в обработчике вызываемого события - а таковых данных в этом коде ещё нет - они появятся позже, когда объект уже будет создан, а файл - открыт для доступа.
Конечно, возможна ситуация, когда данный метод будет вызван не действием пользователя, а из какого-либо другого фрагмета кода (например, this->Button1->Click(). Тогда, согласен, данные другого фрагмента будут потеряны, но эту проблему нужно будет решать в том самом "другом" коде.
Более того, в этом случае, "глушение" исключения внутри обработчика OnButton будет просто неправильным, ибо как-то требуется передать сообщение об ошибке вызываемой функции вызвавшей. А иного способа придумать сложно.
294
18 ноября 2006 года
Plisteron
982 / / 29.08.2003
[QUOTE=el scorpio]Более того, в этом случае, "глушение" исключения внутри обработчика OnButton будет просто неправильным, ибо как-то требуется передать сообщение об ошибке вызываемой функции вызвавшей. А иного способа придумать сложно.[/QUOTE]
Легко.
Код:
{
    try
    {
        /* здесь какой-то код */
        this->Button1->Click(); /* <-- что, согласен, крайне не рекомендуется */
    }
    catch(Exception &E)
    {
        /* подчищаем хвосты */
    }
    catch(int &ExternalException)
    {
        if(ExternalException == 1)
        {
            /* сообщаем об обломе  конструкции this->Button1->Click(); */
        }
    }
}

TForm1::Button1Click(TObject *Sender)
{
    try
    {
        /* код */
    }
    catch(Exception &E)
    {
        /* обрабатываем */
        throw 1; /* передаём эстафету */
    }
}

Напоследок пример из жизни. Попробуй-ка применить Application->OnException, если тебе в обработчике исключения надо в лог записать значение локальной переменной. Учитывая, что экземпляров TMyMDIChild может быть несколько, соответственно, в каждом экземпляре значение переменной своё, поэтому глобальная переменная не катит.
246
18 ноября 2006 года
GIZMO
1.8K / / 30.07.2004
[QUOTE=el scorpio]И с чем же, интересно, вы соглашаетесь :confused:
[/QUOTE]

Например выделил я память под какие-то объекты, структуры (чтобы считать допустим настройки из реестра), а new TRegistry взял и не отработал. Легче в этом случае все почистить в catch().
309
18 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=GIZMO]Например выделил я память под какие-то объекты, структуры (чтобы считать допустим настройки из реестра), а new TRegistry взял и не отработал. Легче в этом случае все почистить в catch().[/QUOTE]
Структуры лучше создавать в стеке, а слишком большие объекты - через всё тот же sPointer. И не нужно будет ничего "подчищать" - само удалиться :D


[quote=Plisteron]
Напоследок пример из жизни. Попробуй-ка применить Application->OnException, если тебе в обработчике исключения надо в лог записать значение локальной переменной. Учитывая, что экземпляров TMyMDIChild может быть несколько, соответственно, в каждом экземпляре значение переменной своё, поэтому глобальная переменная не катит.
[/quote]
Прошу уточнить пример.
Если генерируется исключение по команде разработчика, потому что эта самая "локальная переменная" имеет недопустимое с точки зрения алгоритма значение, то всё решается очень просто.
Каждое исключение типа Exception имеет свойство Message. Это свойство формируется из "строки исключения" и "параметров исключения". Так что, всего-навсего, нужно сделать строку сообщения форматируемой, и подставлять в неё параметры
 
Код:
const AnsiString cseMyErrorMessage = "Переменная x в окне %p имеет неправильное значение '%d'";
throw Exception (cseMyErrorMessage, ARRAYOFCONST ((this->Caption, x)));

И полученная строка, в которой символы подстановки будут заменены на указанные параметры, запишется в лог.
294
19 ноября 2006 года
Plisteron
982 / / 29.08.2003
[QUOTE=el scorpio]Структуры лучше создавать в стеке, а слишком большие объекты - через всё тот же sPointer. И не нужно будет ничего "подчищать" - само удалиться :D[/QUOTE]
Ну что ты заладил всё про указатели да про указатели...
Не подчистятся, например:
Printer()->BeginDoc();
CreateFile();
DetDC();
fopen();
FindFirst();
[QUOTE=el scorpio]Прошу уточнить пример.[/QUOTE]
Уточняю. Идёт загрузка данных в БД Oracle в нескольких окнах (некоторые данные берутся из файла, другие являются результатами работы программы). В БД Oracle, естественно, отрабатываются различные ограничения целостности данных и триггеры, в результате работы которых часть данных может быть не принята. Структуры данных разные. Исключение, конечно же, генерится самим Ораклом и передаются в компоненты ODAC, которые, в свою очередь, генерят исключение в моей проге с соответствующей диагностикой от Оракла. Таким образом, я throw в проге в данном случае не использую, исключение генерится не мной. И, по-твоему, я должен в OnException смотреть, в каком окне у меня сгенерировано исключение, посмотреть, какая у меня там структура загружаемых данных, выяснить, какие поля там ключевые, какая ещё пояснительная информация нужна пользователю и продампить всё это в лог? Не проще ли для каждой процедуры загрузки сделать свой обработчик?
Ещё: что будет понятнее пользователю: "Переменная x в окне 0x7fa2 имеет неправильное значение '177374', переменная id равна 456789"
или:"При загрузке лицевого счёта плательщика дата платежа более ранняя, чем дата выставленного счёта. Код плательщика 456789"?

Да, чуть не забыл: в проге есть конструкция, которая гвоворит, принимать ли данные "обо всех" одной транзакцией или же "о каждом" в рамках отдельных транзакций.
 
Код:
if(!checkTransaction->Checked)
    os->StartTransaction();

Соответственно, при "зачистке" я должен посмотреть, была ли начата транзакция в этом соединении, и если да, общая ли она или персональная и принять решение, откатить её или нет. И что мне теперь, в OnException ещё и указатель на соединение с БД передавать и все данные, от которых зависит решение об откате?
309
20 ноября 2006 года
el scorpio
1.1K / / 19.09.2006
Цитата:
Не проще ли для каждой процедуры загрузки сделать свой обработчик?
Ещё: что будет понятнее пользователю: "Переменная x в окне 0x7fa2 имеет неправильное значение '177374', переменная id равна 456789"
или:"При загрузке лицевого счёта плательщика дата платежа более ранняя, чем дата выставленного счёта. Код плательщика 456789"?


А вот на выдачу ТАКИХ сообщений проще настроить саму БД.
И не надо мне рассказывать будто нельзя - в Access такое же делается - а чем Оракл хуже. И не только в VBA - даже в свойствах поля таблицы можно объявить "условие на значение" и "сообщение об ошибке"


P.S.
И вообще, я говорил о ситуации в общем. А не о таком "мегапримере"

294
22 ноября 2006 года
Plisteron
982 / / 29.08.2003
Цитата: el scorpio
А вот на выдачу ТАКИХ сообщений проще настроить саму БД.
И не надо мне рассказывать будто нельзя - в Access такое же делается - а чем Оракл хуже. И не только в VBA - даже в свойствах поля таблицы можно объявить "условие на значение" и "сообщение об ошибке"


Можно, конечно. А вот как насчёт алгоритма принятия решения об откате транзакции? Я ответа не получил.

Цитата: el scorpio
P.S.
И вообще, я говорил о ситуации в общем. А не о таком "мегапримере"


А "в общем" тем более нельзя что-либо однозначно советовать. Так что не надо говорить: "пользуйтесь тем-то и этим-то".

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог