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

Код: 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
23.02.2020, 13:29
    #39929951
Dmitry Arefiev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
Неужто баг у Эмбы ...
...
Рейтинг: 0 / 0
23.02.2020, 13:49
    #39929956
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
X11,

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

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



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

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
23.02.2020, 13:58
    #39929960
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
X11

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


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



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

Код: 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
23.02.2020, 14:33
    #39929968
asviridenkov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
Polesov,

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

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




?

Резалт := нил
пиши в начале метода.
...
Рейтинг: 0 / 0
23.02.2020, 17:30
    #39929996
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
В общем, использовать нужно так:
Код: 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
23.02.2020, 20:56
    #39930047
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
ёёёёё

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

Тогда код будет выглядеть э-э-э... несколько избыточно )
Код: 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
23.02.2020, 20:59
    #39930049
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
Polesov,

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




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


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

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

перед Free и FreeAndNil проверка на nil или assigned не нужна нигде и никогда.
...
Рейтинг: 0 / 0
24.02.2020, 14:21
    #39930199
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
А если Object1.Free, то проверять надо.
Правильно?
...
Рейтинг: 0 / 0
24.02.2020, 14:38
    #39930207
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
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
24.02.2020, 15:06
    #39930218
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан
Я не знаю, может в более ранних версиях Delphi было по-другому. Уже точно не помню.
Ладно.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Assigned(TDictionary<>) возвращает True, хотя объект ещё не создан / 25 сообщений из 25, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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