Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.08.2009, 22:49   #1
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию Размер динамического массива не через Length

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

Как, не используя функции Length и High, узнать размер динамического массива или строки.
Sibedir вне форума Ответить с цитированием
Старый 24.08.2009, 23:17   #2
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Цитата:
Сообщение от Sibedir Посмотреть сообщение
Я уже, кажется, спрашивал, но так и не разобрался, а проблема актуальна. Может чё нового скажите.

Как, не используя функции Length и High, узнать размер динамического массива или строки.
Сохранить в допольнительной переменной (например integer) тот самый размер массива, в месте где Вы и выделяите место в памяти под массив. Разве не логично ? Или язые за вас все должен делать ?
BOBAH13 вне форума Ответить с цитированием
Старый 24.08.2009, 23:46   #3
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию

Цитата:
Разве не логично?
Нет, если уж на то пошло, не логично.
Менеджер памяти (так вроди называется) выделяет память под любую переменну. Эта переменная - по сути указатель на адрес начала данных. Система сама запоминает начало и размер участка памяти выделенную под переменную. Этот размер она и проверяет при приведении типов. Зачем мне еще одну переменную вводить. Это ли не нарушение логиги.

С простыми типами все соответственно просто. Даже с классами нет ничего сложного. Отступил от указателя на объект 40 байт назад - вот вам и размер объекта.
Но с динамическими массивами дело обстоит иначе. Перебрал все доступное адресное пространство (ну или точнее - все доступное адресное пространство в моем понимании) и не нашел ни одного указателя, который можно было бы интерпритировать, как размер строки:
1. Создал строку S размером N
2. Перебрал все указатели от @S вниз и вверх до ошибки (я с памятью работаю весьма посредственно).
3. Сравнил все PInteger (@S+d)^ на равенство N
НЕ НАШЕЛ.
Не, ну были конечно, но это чистое совпадение. Ни какой закономерности.

ВОПРОС: Как, собственно, система узнает размер массива. Может быть она хранит размеры динамических массивов, как особо важную информацию, вне адресного пространства программы.
Sibedir вне форума Ответить с цитированием
Старый 24.08.2009, 23:54   #4
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Строка - в Windows это место в памяти которое является последовательностью символов до нулевого. Таким образом можно определить размер (длину) строки.

Что на счет массива, это место в куче, и то какого размера оно, к сожалению где то было у меня, как зная Pointer получить размер под выделеную память по этому указателю (имеется ввиду GetMem & FreeMem). Точно не скажу, но помниматься именно интепритируемый физический адресс в адрессное пространство приложения (0x00000000 - 0xffffffff в 32х) сам адресс уже хранит размер выделенного пространства (в этом я не уверен, т.к. найти доказательства не могу, а плюс к этому google не отменяли)

Собственно, с другой стороны, зачем надо выдумывать, если вам предложена Length и т.п. ?

Последний раз редактировалось BOBAH13; 24.08.2009 в 23:58.
BOBAH13 вне форума Ответить с цитированием
Старый 25.08.2009, 00:08   #5
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию

Цитата:
Собственно, с другой стороны, зачем надо выдумывать, если вам предложена Length и т.п. ?
Собственно, затем, что у меня есть только Pointer.

Цитата:
Что на счет массива, это место в куче, и то какого размера оно, к сожалению где то было у меня, как зная Pointer получить размер под выделеную память по этому указателю (имеется ввиду GetMem & FreeMem).
Я был бы вам черезвычайно признателен...

P.S.: На счет
Цитата:
Строка - в Windows это место в памяти которое является последовательностью символов до нулевого. Таким образом можно определить размер (длину) строки.
Это вы про PChar, а со строкой в Delphi история интересная:
Код:
var
  s: String;
begin
  s := '01234567890';
  s [3] := #0;
  ShowMessage (IntToStr (Length (s)) + ' - ' + s);
end;
По запросу
как зная Pointer получить размер под выделенную память по этому указателю
нашел
Код:
function GetPointerSize(const P: Pointer): Integer;
begin
 if P = nil then
  Result := -1
 else
  Result := Integer(Pointer((Integer(p) - 4))^) and $7FFFFFFC - 4;
end;
Но это не то. Мне то нужно какраз в кучу из переменной данные загонять, а не из кучи их вытаскивать.

Последний раз редактировалось Stilet; 25.08.2009 в 08:43.
Sibedir вне форума Ответить с цитированием
Старый 25.08.2009, 08:21   #6
alexBlack
Участник клуба
 
Регистрация: 12.10.2007
Сообщений: 1,204
По умолчанию

Цитата:
Сообщение от Sibedir Посмотреть сообщение
...
1. Создал строку S размером N
2. Перебрал все указатели от @S вниз и вверх до ошибки (я с памятью работаю весьма посредственно).
3. Сравнил все PInteger (@S+d)^ на равенство N
....
Немного не так. Не @S а pointer(S), т.к. строка - уже указатель.

Код:
type
  PStrRec = ^StrRec;
  StrRec = packed record
    refCnt: Longint;
    length: Longint;
  end;

var S:String;
    R:PStrRec;
begin
   S := 'test';
   R := PStrRec(pointer(integer(pointer(S))-sizeof(StrRec)));
   WriteLn(R.refCnt);    // 1
   WriteLn(R.length);    // 4
то-же самое для динамических массивов:

Цитата:
Dynamic array memory layout (Win32 only)
Offset Contents
-8 32-bit reference-count
-4 32-bit length indicator (number of elements)
0..Length * (size of element) -1 array elements
alexBlack вне форума Ответить с цитированием
Старый 25.08.2009, 22:48   #7
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию

Спасибо, alexBlack и BOBAH13.
Какая же все-таки глупая ошибка. Совсем забыл, что строка - это и есть указатель. Теперь все работает:
Код:
type
  TMyType = Byte;
var
  a: array of TMyType;
  ValueLength: Pointer;

...

  ValueLength := Pointer (Integer (Pointer (a)) - 4);
  ShowMessage ('Length = ' + IntToStr (Integer (ValueLength^)));
Правда не совсем все. Что если мне не известен тип элементов массива, и мне нужно узнать не количество элементов массива, а его реальный размер (Length (a) * SizeOf (<Тип элемента>)).
Sibedir вне форума Ответить с цитированием
Старый 26.08.2009, 10:52   #8
alexBlack
Участник клуба
 
Регистрация: 12.10.2007
Сообщений: 1,204
По умолчанию

Весь блок, выделенный под массив, получен вызовом GetMem (вызывается из SetLength). Следовательно, для ссылки (a-8) можно получить размер блока вызовом GetPointerSize, которую Вы приводили выше.

Код:
var A:array of integer;
    P:Pointer;
    PSize: integer;
begin
   SetLength(A, 10000);
   P := Pointer(Integer(Pointer(A)) - 4);
   WriteLn(PInteger(P)^);    // 10000

   P := Pointer(Integer(Pointer(A)) - 8);
   WriteLn(PInteger(P)^);    // 1

   P := Pointer(Integer(Pointer(A)) - 8);
   PSize := GetPointerSize(P);
   writeln(inttostr(PSize)); // 40236
// Есть одно "но".
Судя по всему был изменен менеджер памяти и приведенная выше функция GetPointerSize, например, в Delphi 10 работает только для больших блоков. Поэтому в примере взят такой размер. Для малых блоков по смещению -4 хранится ссылка на внутреннюю структуру и уже в ней, вероятно, размер.
alexBlack вне форума Ответить с цитированием
Старый 26.08.2009, 14:04   #9
OCTAGRAM
Oldschool geek
Форумчанин
 
Аватар для OCTAGRAM
 
Регистрация: 09.03.2009
Сообщений: 611
По умолчанию

В Delphi можно подменить менеджер памяти, например, ShareMM и FastMM так делают. Можно подменить менеджер памяти на свою отладочную версию, и затем консультироваться с отладочной версией по поводу размеров блоков. Возможно, такой отладочный менеджер памяти уже идёт в комплекте.
If you want to get to the top, you have to start at the bottom

http://pascal.net.ru/
OCTAGRAM вне форума Ответить с цитированием
Старый 29.08.2009, 19:42   #10
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию

А в каком модуле описана процедура GetPointerSize? У меня Delphi 7.

А-а-а. Нашел. Вы наверное имели в виду вот это:
Код:
function GetPointerSize(const P: Pointer): Integer;
begin
  if P = nil then
    Result := -1
  else
    Result := Integer(Pointer((Integer(p) - 4))^) and $7FFFFFFC - 4;
end;

Последний раз редактировалось Sibedir; 29.08.2009 в 20:04.
Sibedir вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сохранение динамического массива Horus92 Помощь студентам 3 07.05.2009 12:36
Удаление динамического массива Сергей089 Общие вопросы C/C++ 3 08.03.2009 13:13
Напомните как задать размер динамического массива Arassir Помощь студентам 4 08.03.2009 13:02
Удаление элементов из динамического массива dashulka Общие вопросы Delphi 4 31.10.2008 14:03
Удаление элемента динамического массива Dogmat Помощь студентам 6 13.07.2008 14:33