powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
25 сообщений из 25, страница 1 из 1
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929948
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача простая вроде бы. Держать в памяти некий список и из него получать данные по ключу.
В частности, для именования колонок сетки.
Вот весь модуль

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
unit uFieldsDefs;

interface

uses
  System.Generics.Collections;


type
  IKvxFieldsDefs = interface
  ['{0040A25D-B3E6-42ED-A625-1D58DD7EB47F}']

    function KvxFieldsDefs(const sTableName: string): TDictionary<String, String>;
  end;


  TKvxFieldsDefs = class(TInterfacedObject, IKvxFieldsDefs)
  public

    function KvxFieldsDefs(const sTableName: string): TDictionary<String, String>;
  end;

Var
  KvxFieldsDefs: IKvxFieldsDefs;

implementation

uses MainModule, Uni, SysUtils;




{ TKvxFieldsDefs }


function TKvxFieldsDefs.KvxFieldsDefs(const sTableName: string): TDictionary<String, String>;
const
  constSQL = 'SELECT R.RDB$FIELD_NAME, R.RDB$DESCRIPTION FROM RDB$RELATION_FIELDS R ' + ' WHERE R.RDB$SYSTEM_FLAG = 0 AND UPPER(R.RDB$RELATION_NAME) = UPPER(:TABLE_NAME)';
Var
  q: TUniQuery;
begin
  if sTableName.IsEmpty then exit;

  if Not Assigned(Result) then
    Result := TDictionary<String, String>.Create
  else
    Result.Clear;// ошибка здесь

  q := UniMainModule.CreateUniQuery;
  q.SQL.Text := constSQL;
  q.Params[0].AsString := sTableName;

  q.open;
  if q.RecordCount <= 0 then exit;

  while not UniMainModule.qRegionsGetSTATEINDEX.Eof do
  begin
    Result.Add(q.Fields[0].AsString, q.Fields[1].AsString);
    q.Next;
  end;// while

  UniMainModule.qRegionsGetSTATEINDEX.close;
end;


end.



Вот так создаю:
Код: pascal
1.
KvxFieldsDefs := TKvxFieldsDefs.create;



Использование
Код: pascal
1.
2.
3.
4.
5.
  for I := 0 to pred(grid.Columns.Count) do
  begin
    KvxFieldsDefs.KvxFieldsDefs(sTableName).TryGetValue(grid.Columns[i].FieldName, s);
    grid.Columns[i].Title.Caption := s;
  end;



Access violation at address 00AEA017 in module XXX. Read of address 00000006

Почему-то не выполняется строка
Result := TDictionary<String, String>.Create
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929951
Фотография Dmitry Arefiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Неужто баг у Эмбы ...
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929956
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

А кто этот мусор (Result) будет инициализировать?
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929957
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Т.е. в данном случае результат функции, как объект всегда нужно только создавтаь?

Т.е. всегда должно быть только так:
Код: pascal
1.
Result := TDictionary<String, String>.Create



?
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929959
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
тогда утечки

Unexpected Memory Leak
---------------------------
An unexpected memory leak has occurred. The unexpected small block leaks are:

45 - 52 bytes: TDictionary<System.string,System.string> x 57
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929960
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11

Код: pascal
1.
  if Not Assigned(Result) then


Result - это значение на стеке, и, с высокой вероятностью, там содержится мусор.
Поэтому условие if Not Assigned(Result) then не выполняется.
Но есть вероятность, что там будет nil )
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929961
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
3.
4.
  if Result = nil then
    Result := TDictionary<String, String>.Create
  else
    Result.Clear;



та же ошибка
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929963
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11, это был сарказм )
Нельзя рассчитывать на то, что на стеке значение переменной TObject будет инициализировано в nil.
Если не ошибаюсь, на стеке инициализируются только переменные типа string.
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929966
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем, переделал вот так, утечек нет

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
unit uFieldsDefs;

interface

uses
  System.Generics.Collections;


type
  IKvxFieldsDefs = interface
  ['{0040A25D-B3E6-42ED-A625-1D58DD7EB47F}']
    procedure SetTableName(const TableName: string);
    function  GetFieldsDefs: TDictionary<String, String>;
  end;


  TKvxFieldsDefs = class(TInterfacedObject, IKvxFieldsDefs)
  private
    list: TDictionary<String, String>;


  public
    procedure SetTableName(const TableName: string);
    function  GetFieldsDefs: TDictionary<String, String>;

    constructor create;
    destructor Destroy; override;
  end;

Var
  KvxFieldsDefs: IKvxFieldsDefs;

implementation

uses MainModule, Uni, SysUtils;




{ TKvxFieldsDefs }



constructor TKvxFieldsDefs.create;
begin
  list := TDictionary<String, String>.Create
end;

destructor TKvxFieldsDefs.Destroy;
begin
  if Assigned(list) then
    FreeAndNil(list);

  inherited;
end;

function TKvxFieldsDefs.GetFieldsDefs: TDictionary<String, String>;
begin
  result := list;
end;


procedure TKvxFieldsDefs.SetTableName(const TableName: string);
const
  constSQL = 'SELECT R.RDB$FIELD_NAME, R.RDB$DESCRIPTION FROM RDB$RELATION_FIELDS R ' + ' WHERE R.RDB$SYSTEM_FLAG = 0 AND UPPER(R.RDB$RELATION_NAME) = UPPER(:TABLE_NAME)';
Var
  q: TUniQuery;
begin

  if TableName.IsEmpty then exit;

  if list = nil then
    list := TDictionary<String, String>.Create
  else
    list.Clear;

  q := UniMainModule.CreateUniQuery;
  q.SQL.Text := constSQL;
  q.Params[0].AsString := TableName;
  q.SpecificOptions.Values['FetchAll'] := 'True';

  q.open;

  if q.RecordCount <= 0 then exit;

  while not q.Eof do
  begin
    list.Add(q.Fields[0].AsString, UTF8ToString(rawByteString(q.Fields[1].AsString)));
    q.Next;
  end;// while

  q.close;
end;

end.



использование
Код: pascal
1.
2.
3.
4.
5.
6.
7.
  KvxFieldsDefs.SetTableName(sTableName);

  for I := 0 to pred(grid.Columns.Count) do
  begin
    KvxFieldsDefs.GetFieldsDefs.TryGetValue(grid.Columns[i].FieldName, s);
    grid.Columns[i].Title.Caption := s;
  end;
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929968
asviridenkov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

Все управляемые типы
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929977
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А что означает восклицательный знак слева вверху?
Всё компилирует, всё работает. В этом модуле нет подсказок и предупреждение компилятора. Первый раз такое вижу.
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929979
ёёёёё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11
Т.е. в данном случае результат функции, как объект всегда нужно только создавтаь?

Т.е. всегда должно быть только так:
Код: pascal
1.
Result := TDictionary<String, String>.Create




?

Резалт := нил
пиши в начале метода.
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39929996
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем, использовать нужно так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Var
 i: integer;
 s: string;
 list: TDictionary<String, String>;
begin
...
....
 KvxFieldsDefs.SetTableName(sTableName);// строим список

  list := KvxFieldsDefs.GetFieldsDefs(sTableName);

  for I := 0 to pred(grid.Columns.Count) do
  begin
    list.TryGetValue(grid.Columns[i].FieldName, s);
    grid.Columns[i].Title.Caption := s;
  end;



а то получается так, что все эти списки пересоздаются в цикле по количеству колонок
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930047
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ёёёёё

Резалт := нил
пиши в начале метода.

Тогда код будет выглядеть э-э-э... несколько избыточно )
Код: pascal
1.
2.
3.
4.
5.
6.
begin
  Result := nil;
  if not Assigned( Result ) then
    Result := TDictionary<String, String>.Create
  else
    Result.Clear;
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930049
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

ну я там уже переделал
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930083
Dmitry Arefiev
Неужто баг у Эмбы ...


Нет, ибо настоящий презик выглядит вот именно так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  windows, System.SysUtils, System.Generics.Collections;

function GetObjectClass(APointer: Pointer): TClass;
{$IFDEF MSWINDOWS}
var
  LMemInfo: TMemoryBasicInformation;

  { Checks whether the given address is a valid address for a VMT entry. }
  function IsValidVMTAddress(APAddress: Pointer): Boolean;
  begin
    { Do some basic pointer checks: Must be dword aligned and beyond 64K }
    if (UIntPtr(APAddress) > 65535) and (UIntPtr(APAddress) and 3 = 0) then
    begin
      { Do we need to recheck the virtual memory? }
      if (UIntPtr(LMemInfo.BaseAddress) > UIntPtr(APAddress)) or
        ((UIntPtr(LMemInfo.BaseAddress) + NativeUInt(LMemInfo.RegionSize)) <
        (UIntPtr(APAddress) + SizeOf(Pointer))) then
      begin
        { Get the VM status for the pointer }
        LMemInfo.RegionSize := 0;
        VirtualQuery(APAddress, LMemInfo, SizeOf(LMemInfo));
      end;
      { Check the readability of the memory address }
      Result := (NativeUInt(LMemInfo.RegionSize) >= SizeOf(Pointer)) and
        (LMemInfo.State = MEM_COMMIT) and
        (LMemInfo.Protect and (PAGE_READONLY or PAGE_READWRITE or
        PAGE_EXECUTE or PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE or
        PAGE_EXECUTE_WRITECOPY) <> 0) and (LMemInfo.Protect and PAGE_GUARD = 0);
    end
    else
      Result := False;
  end;

{ Returns true if AClassPointer points to a class VMT }
  function InternalIsValidClass(AClassPointer: Pointer;
    ADepth: Integer = 0): Boolean;
  var
    LParentClassSelfPointer: PPointer;
  begin
    { Check that the self pointer as well as parent class self pointer addresses
      are valid }
    if (ADepth < 1000) and IsValidVMTAddress
      (Pointer(PByte(AClassPointer) + vmtSelfPtr)) and
      IsValidVMTAddress(Pointer(PByte(AClassPointer) + vmtParent)) then
    begin
      { Get a pointer to the parent class' self pointer }
      LParentClassSelfPointer := PPointer(PByte(AClassPointer) + vmtParent)^;
      { Check that the self pointer as well as the parent class is valid }
      Result := (PPointer(PByte(AClassPointer) + vmtSelfPtr)^ = AClassPointer)
        and ((LParentClassSelfPointer = nil) or
        (IsValidVMTAddress(LParentClassSelfPointer) and
        InternalIsValidClass(LParentClassSelfPointer^, ADepth + 1)));
    end
    else
      Result := False;
  end;

begin
  { Get the class pointer from the (suspected) object }
  Result := TClass(PNativeUInt(APointer)^);
  { No VM info yet }
  LMemInfo.RegionSize := 0;
  { Check the block }
  if not InternalIsValidClass(Pointer(Result), 0) then
    Result := nil;
{$ELSE !MSWINDOWS}
begin
  { Not currently supported under Linux / OS X }
  Result := nil;
{$ENDIF MSWINDOWS}
end;

procedure Test(IsCreate: Boolean);
type
  sc = TDictionary<String, String>;
var
  list: sc;
  c: TClass;
begin
  if IsCreate then
    list := sc.Create;

  c := GetObjectClass(list);
  if c <> nil then
  begin
    Writeln('Объект есть: ' + c.ClassName);
    list.Clear;
    list.Destroy;
  end
  else
    Writeln('Объект нет');
end;

var
  i: Char;

begin
  try
    repeat
      Writeln('Создать объект? Y\N\Q');
      Readln(i);

      Test((i = 'Y') or (i = 'y'));
    until (i = 'Q') or (i = 'q');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.

...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930086
На самом деле код хоть и выглядит страшным, но он выйдет уже на
Код: pascal
1.
if (UIntPtr(APAddress) > 65535) and (UIntPtr(APAddress) and 3 = 0) then




Не пройдя проверку.
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930136
Фотография Dmitry Arefiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Круто :)
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930145
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11


Код: pascal
1.
2.
  if Assigned(list) then
    FreeAndNil(list);

Выделенное лишнее
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930151
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Квейд, мне кажется, будет AV если вызвать FreeAndNil без проверки на несуществующем эеземпляре.
Сейчас тестировать нет времени, но у меня, ЕМНИП, были проблемы, из-за чем же я и начал добавлять проверку.
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930156
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11
Квейд, мне кажется, будет AV если вызвать FreeAndNil без проверки на несуществующем эеземпляре.
Ни в коем случае не будет.
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930186
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

перед Free и FreeAndNil проверка на nil или assigned не нужна нигде и никогда.
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930199
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А если Object1.Free, то проверять надо.
Правильно?
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930207
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11
А если Object1.Free, то проверять надо.
Правильно?
Не надо

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
procedure TObject.Free;
begin
// under ARC, this method isn't actually called since the compiler translates
// the call to be a mere nil assignment to the instance variable, which then calls _InstClear
{$IFNDEF AUTOREFCOUNT}
  if Self <> nil then
    Destroy;
{$ENDIF}
end;
...
Рейтинг: 0 / 0
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
    #39930218
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я не знаю, может в более ранних версиях Delphi было по-другому. Уже точно не помню.
Ладно.
...
Рейтинг: 0 / 0
25 сообщений из 25, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]