Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

использование динамического массива как члена класса [D6, WinXP]


Igor_ ©   (2002-12-11 18:17:00) 

Подскажите пожайлуста, что делаю не так. У меня членом класса является
динамический массив и при любом к нему обращении вызывается Acces violation.
массив из элементов TDB_Field

type TDB_Field = record
FiedName: string;
Value: variant;
end;//type DBField = record


- при чем исключение вызывается только тогда,
когда я пытаюсь использовать класс, в котором этот массив, когда просто создаю
переменную типа Ar: array of TDB_Field - все нормально

вот объявление и реализация класса:

type TDB_Field = record
FiedName: string;
Value: variant;
end;//type DBField = record


type
TDB_Record = class
public
constructor Create();
procedure Load(Q: TQuery; TablName, KeyField: string; KeyFieldValue: string);
private
_Fields: array of TDB_Field;
end;//TDBRecord = class

implementation

uses
Dialogs;

//------------------------
///// TDBRecord ////
//-------------------------
constructor TDB_Record.Create;
begin
_Fields := Nil; /// ЗДЕСЬ ACCESS VIOLATION !!!
end;
//--------------------------
// загружаем заданную запись из БД
procedure TDB_Record.Load(Q: TQuery; TablName, KeyField: string;
KeyFieldValue: string);
var
i:integer;
begin
// получаем запись из таблицы по указанному ключевому полю
with Q do
begin
Close; SQl.Clear;
SQL.Add("Select * from "+ TablName);
SQL.Add("Where "+KeyField +"="+ KeyFieldValue);
MessageDlg(SQL.Text, mtWarning, [mbOK], 0);
Open;
end;//with Q do

SetLength(_Fields, 0); /// ЗДЕСЬ ТОЖЕ ACCESS VIOLATION !!!
// находим имена полей и их значения
for i:=0 to (Q.Fields.Count - 1) do
begin
SetLength(_Fields, i + 1);
_Fields[i].FiedName := Q.Fields.Fields[i].FieldName;
_Fields[i].Value := Q.Fields.Fields[i].Value;
end;//for i:=0 to (Qt.Fields.Count - 1) do

Q.Close;
end;


где у меня ошибка?
Спасибо.


Igor_   (2002-12-13 17:28:00) [1]

:)


Matolch   (2002-12-13 10:31:00) [2]

Пыттался раззарядить атомосферу
А так - ну, не за что, пожалста. (краснею и шаркаю ножкой)


Igor_   (2002-12-13 10:11:00) [3]

2Matolch © ??? - спасибо за совет!!!!

2Бурундук - действительно спасибо, тут динамический массив не при чем, это я прогнал - по дурацки вызвал конструктор TDB_Record. Сделал правильный вызов и все заработало. Спасибо.


Matolch   (2002-12-13 08:02:00) [4]

/// ЗДЕСЬ ACCESS VIOLATION !!!


Fantasist   (2002-12-12 21:23:00) [5]


> навевает подозрения, что в метод передан неверный Self,
>


Вообще-то, Self в конструктор, строго говоря, не передается - он его конструирует. Однако, при вызове через переменную, компилятор заносит ее в регистр, и высталяет специальный флаг, по которому внутри кода конструктора определяется, что конструировать self(в смысле выделять для него память) не надо, и в него попадает значение сохраненное в регистре. Так что догадка скорее всего верна.



> И можно поподробнее на счет "из-за неправильного синтаксиса
>
> вызова конструктора типа Obj.Create" - как это отследить?


Отследить это можно так:
в конструкторе
>constructor TDB_Record.Create;
>begin
>_Fields := Nil; /// ЗДЕСЬ ACCESS VIOLATION !!!
>end;

ставишь брекпойнт на begin. Когда он вызовется нажимаешь Ctrl+F7, и вводишь dl. Если видишь значение 1 - то вызов был произведен как это обычно положенно. Если нет, то вызов был произведен через переменную, что, скорее всего, не правильно. Так в Delphi6. Далее открываешь окно Call Stack, и находишь откуда конструктор вызван - идешь в это метод и смотришь.


Бурундук   (2002-12-12 14:21:00) [6]

Объект должен быть создан так:
var Rec: TDB_Record;

Rec := TDB_Record.Create(...);
// а не Rec.Create(...); - вот что я имел ввиду под
// неправильным синтаксисом.

А чтобы проверить, валидный ли селф, попробуй убрать из
конструктора _Fields := nil;
(при конструировании все поля автоматически обнуляются и так)
и вызови какую-нибудь ф-ю, например, ClassName -
и посмотри, не будет ли AV, а также, что она возвратит.


Igor_   (2002-12-12 14:08:00) [7]

2Бурундук
По моему что-то вроде этого и происходит, т.к. исключение вызывается вообщем при любом обращении к массиву.
А как вообще проверить какой Self передан?
И можно поподробнее на счет "из-за неправильного синтаксиса
вызова конструктора типа Obj.Create" - как это отследить?


Бурундук   (2002-12-12 13:52:00) [8]

VaS © (12.12.02 13:26)
Всё это делается автоматически.

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

Следующий код
>constructor TDB_Record.Create;
>begin
>_Fields := Nil; /// ЗДЕСЬ ACCESS VIOLATION !!!
>end;
навевает подозрения, что в метод передан неверный Self,
например, из-за неправильного синтаксиса
вызова конструктора типа Obj.Create;


KSergey   (2002-12-12 13:46:00) [9]

А вообще-то вот это
_Fields := Nil;
и
SetLength(_Fields, 0);
в конструкторе - нужно ли?
Ну не выделена память - да и ладно. И так это понятно.


VaS   (2002-12-12 13:26:00) [10]


constructor TDB_Record.Create;
begin
SetLength(_Fields, 0);
end;
...
procedure TDB_Record.Load(Q: TQuery; TablName, KeyField: string;
KeyFieldValue: string);
...
SetLength(_Fields, Q.Fields.Count); (c)TTCustomDelphiMaster
...
destructor TDB_Record.Destroy;
begin
Finalize(_Fields);
end;


Igor_   (2002-12-12 12:13:00) [11]

2TTCustomDelphiMaster ©
SetLength(_Fields, Q.Fields.Count)
не помогло, тут тоже возникает исключение - собственно никакой
разницы в подходе я не вижу сразу поставить длину массива или постепенно ее наращивать.

Может кто нибудь еще что подскажет? Или это просто глюк Delphi?


TTCustomDelphiMaster   (2002-12-11 18:34:00) [12]

constructor TDB_Record.Create;
begin
end;

procedure TDB_Record.Load(Q: TQuery; TablName, KeyField: string;
KeyFieldValue: string);
var
i:integer;
begin
with Q do
begin
Close; SQl.Clear;
SQL.Add("Select * from "+ TablName);
SQL.Add("Where "+KeyField +"="+ KeyFieldValue);
MessageDlg(SQL.Text, mtWarning, [mbOK], 0);
Open;
end;//with Q do

SetLength(_Fields, Q.Fields.Count);
for i:=0 to (Q.Fields.Count - 1) do
begin
_Fields[i].FiedName := Q.Fields.Fields[i].FieldName;
_Fields[i].Value := Q.Fields.Fields[i].Value;
end;//for i:=0 to (Qt.Fields.Count - 1) do

Q.Close;
end;


Наверх

Титульная страница Поиск, карта сайта Написать письмо