powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Освобождение памяти - Динамический массив из записей
17 сообщений из 17, страница 1 из 1
Освобождение памяти - Динамический массив из записей
    #39824148
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть динамический массив записей
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
type
TSubjectItem = record
  Name: string;
  Value: string;
end;
TSubjectArray = array of TSubjectItem;
...
FItems: TSubjectArray;


Во время работы добавляю в него элементы:
Код: pascal
1.
2.
3.
4.
procedure TSubject.Add(Item: TSubjectItem);
begin
  FItems := FItems + [Item];
end;


При выходе, освобождаю выделенную под нее память память :
Код: pascal
1.
SetLength(FItems, 0);


Так вот, иногда на этом SetLength вываливается ошибка "Invalid pointer operation"
В чем проблема? Записи нужно как-то специально зачищать?
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824173
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerПри выходе, освобождаю выделенную под нее память память :
Код: pascal
1.
SetLength(FItems, 0);

Это не обязательно. Он сам убьется как только выйдет из зоны видимости


SQL-TalkerТак вот, иногда на этом SetLength вываливается ошибка "Invalid pointer operation"
В чем проблема?Где-то портится память.

Подключайте FastMM в FullDebugMode и смотрите
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824195
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Подключил. Получил сообщение об утечке
Проблемы в этой процедуре:
Код: 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.
function Cert_GetSubjectStr(aCertContext: PCCERT_CONTEXT): string;
type
  CERT_RDN_ARRAY = array of CERT_RDN;
var
  i: Integer;
  pvStructInfo: PVOID;
  cbStructInfo: DWORD;
  pCertNameInfo: PCERT_NAME_INFO;
  vRDNAttr: PCERT_RDN_ATTR;
  pszValue: PWIdeChar;
  RDNValueSize: DWORD;
  pInfo: PCCRYPT_OID_INFO;
  szName, szValue: string;
begin
  // декодируем Subject
  if CryptDecodeObject(
    X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
    X509_UNICODE_NAME, //X509_NAME,
    aCertContext.pCertInfo.Subject.pbData,
    aCertContext.pCertInfo.Subject.cbData,
    CRYPT_DECODE_NOCOPY_FLAG,
    nil,
    cbStructInfo
  )
  then
  begin
    GetMem(pvStructInfo, cbStructInfo);
    try
      CryptDecodeObject(
        X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
        X509_UNICODE_NAME, //X509_NAME,
        aCertContext.pCertInfo.Subject.pbData,
        aCertContext.pCertInfo.Subject.cbData,
        CRYPT_DECODE_NOCOPY_FLAG,
        pvStructInfo,
        cbStructInfo
      );

      pCertNameInfo := PCERT_NAME_INFO(pvStructInfo);

      // перебираем массив атрибутов Subject-а
      for i := 0 to (pCertNameInfo.cRDN - 1) do
      begin
        vRDNAttr := CERT_RDN_ARRAY(pCertNameInfo.rgRDN)[i].rgRDNAttr;
        CertRDNValueToStr(vRDNAttr.dwValueType, @vRDNAttr.Value, nil, RDNValueSize);
        if RDNValueSize > 0 then
        begin
          GetMem(pszValue, RDNValueSize);       // <<<<<----- Строка 1323
          try
            CertRDNValueToStr({vRDNAttr.dwValueType} CERT_RDN_UNICODE_STRING, @vRDNAttr.Value, pszValue, RDNValueSize);
            pInfo := CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, PChar(vRDNAttr.pszObjId), 0);
            szName := PWideChar(pInfo.pwszName);
            szValue := PWideChar(pszValue);
            Result := Result + szName + '=' + szValue + #13#10;
          finally
            FreeMem(pszValue, RDNValueSize);        // <<<<<----- Строка 1331
          end;
        end;
      end;
    finally
      FreeMem(pvStructInfo, cbStructInfo);
    end;
  end;

  Result := Trim(Result);
end;


Проблемы связаны с вызовом CertRDNValueToStr в строке 1325 - если этот вызов закомментировать, то утечки не будет...
Но что тут не так??
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824197
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Скрин сообщения об утечке:
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824198
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"Invalid pointer operation" - это ошибка, которую генерирует дельфёвый менеджер памяти, если ему подсовывают левый (неизвестный ему) указатель (или nil).

TSubject.Add случайно не вызывается одновременно из параллельных потоков?
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824199
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer,

Нет, тут все в одном потоке
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824204
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
FreeMem(pszValue, RDNValueSize);



замени на
Код: pascal
1.
FreeMem(pszValue); 
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824209
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

В FullDebugMode он ещё и лог-файл создаёт, а если включить map-файл, то он даже строчки кода туда засунет где что происходит.
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824211
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrb,

ничего не изменилось
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824232
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerСкрин сообщения об утечке:

Это не утечка. Это Memory Corrupted - повреждение памяти. О чем я и говорил
SQL-TalkerНо что тут не так??То, что вы используете случайный размер памяти

SQL-Talker
Код: pascal
1.
 CertRDNValueToStr(vRDNAttr.dwValueType, @vRDNAttr.Value, nil, RDNValueSize);

https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-certrdnvaluetostra psz

A pointer to a buffer to receive the returned string.

csz

Size, in characters, allocated for the returned string. The size must include the terminating NULL character.

Return Value
Returns the number of characters converted, including the terminating NULL character. If psz is NULL or csz is zero, returns the required size of the destination string.

Remarks
If psz is not NULL and csz is not zero, the returned psz is always a possibly empty null-terminated string.
SQL-Talker
Код: pascal
1.
CertRDNValueToStr(vRDNAttr.dwValueType, @vRDNAttr.Value, nil, RDNValueSize);
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824255
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

авторIf psz is NULL or csz is zero, returns the required size of the destination string.
psz я и выставляю в nil
прямо сейчас выставил RDNValueSize := 0; перед вызовом - после вызова RDNValueSize = 0 !!! черт возьми!
что не так с вызовом?
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824259
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talkerчто не так с вызовом? Return Value
Returns the number of characters converted, including the terminating NULL character. If psz is NULL or csz is zero, returns the required size of the destination string.
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824260
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

Код: pascal
1.
RDNValueSize := CertRDNValueToStr({vRDNAttr.dwValueType} CERT_RDN_UNICODE_STRING, @vRDNAttr.Value, nil, 0);
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #39824263
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Блин, смотрю в книгу - вижу фигу.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Освобождение памяти - Динамический массив из записей
    #40030248
Фотография imkot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

Под XE8 у меня проблемы с чтением данных в PWIdeChar при помощи CertRDNValueToStr
В конце концов возникает ошибка работы с памятью.

Вот так работает:
Код: 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.
function GetCertSubjectAttr(Cert: PCCERT_CONTEXT): String;
var
  i: Integer;
  pvStructInfo: PVOID;
  cbStructInfo: DWORD;
  pCertNameInfo: PCERT_NAME_INFO;
  vRDNAttr: PCERT_RDN_ATTR;
  psz: array of WideChar; // Заменяем на массив
  RDNValueSize, RDNValueSizeRead: DWORD;
  pInfo: PCCRYPT_OID_INFO;
  S: string;
begin
  Result := '';
  // декодируем Subject
  if CryptDecodeObject(
    X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
    X509_UNICODE_NAME, //X509_NAME,
    Cert.pCertInfo.Subject.pbData,
    Cert.pCertInfo.Subject.cbData,
    CRYPT_DECODE_NOCOPY_FLAG,
    nil,
    cbStructInfo
  )
  then
  begin
    GetMem(pvStructInfo, cbStructInfo);
    try
      CryptDecodeObject(
        X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
        X509_UNICODE_NAME, //X509_NAME,
        Cert.pCertInfo.Subject.pbData,
        Cert.pCertInfo.Subject.cbData,
        CRYPT_DECODE_NOCOPY_FLAG,
        pvStructInfo,
        cbStructInfo
      );

      pCertNameInfo := PCERT_NAME_INFO(pvStructInfo);

      // перебираем массив атрибутов Subject-а
      for i := 0 to (pCertNameInfo.cRDN-1) do
      begin
        vRDNAttr := CERT_RDN_ARRAY(pCertNameInfo.rgRDN)[i].rgRDNAttr;
//        RDNValueSize := CertRDNValueToStr(vRDNAttr.dwValueType, @vRDNAttr.Value, nil, 0);
        RDNValueSize := CertRDNValueToStr(CERT_RDN_UNICODE_STRING, @vRDNAttr.Value, nil, 0);
        if RDNValueSize > 0 then
        begin
          SetLength(psz, RDNValueSize); // Выделяем память таким образом, потому что при использовании GetMem|FreeMem в конце концов ловим ошибку.
          try
            RDNValueSizeRead := CertRDNValueToStr(CERT_RDN_UNICODE_STRING, @vRDNAttr.Value, @psz[0], RDNValueSize);
            pInfo := CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, PChar(vRDNAttr.pszObjId), 0);
            if Result <> '' then
              Result := Result + sLineBreak;
            if Assigned(pInfo) then
            begin
              S := WideCharToString(pInfo.pwszName);
              Result := Result + S + '=';
            end;
            S := WideCharLenToString(@psz[0], RDNValueSizeRead);
            Result := Result + S;
          finally
            pInfo := nil;
            SetLength(psz, 0);
          end;
        end;
      end;
    finally
      FreeMem(pvStructInfo, cbStructInfo);
    end;
  end;
end;
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #40030253
Gerasimenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
imkot,

замени на TObjectList
...
Рейтинг: 0 / 0
Освобождение памяти - Динамический массив из записей
    #40030280
Фотография imkot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gerasimenko,

да я баран, надо же так делать

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
var
 psz: PWideChar;
 RDNValueSize: DWORD;
begin
  RDNValueSize := n; 
  GetMem(psz, RDNValueSize * SizeOf(WideChar));
  FreeMem(psz);
end
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Освобождение памяти - Динамический массив из записей
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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