Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.03.18;
Скачать: CL | DM;

Вниз

Копируется ли строка про добавлении в ListBox или нет ?   Найти похожие ветки 

 
Альф   (2007-01-24 10:43) [0]

Есть массив строк

var
 astr: array of string;

необходимо это массив визуализировать - например вывести в ListBox.

Вопрос - будет ли дублироваться в памяти каждая строка при добавлении из массива строк в ListBox.Items ?
Или же физически строка в памяти будет одна - а в ListBox.Items будет только ссылка на неё ?


 
Rouse_ ©   (2007-01-24 10:45) [1]

Будет дублироваться...


 
TRUNK ©   (2007-01-24 11:01) [2]

По идее для строк применяется правило CopyOnWrite, т.е. при простом копировании строки происходит только копирование указателя, а уже при попытке изменения скопированной строки происходит создание второй строки с другим указателем.


 
Игорь Шевченко ©   (2007-01-24 11:20) [3]

Rouse_ ©   (24.01.07 10:45) [1]

Не будет дублироваться


 
Rouse_ ©   (2007-01-24 11:58) [4]


> Не будет дублироваться

Да? Хм...

function TListBoxStrings.Add(const S: string): Integer;
begin
 Result := -1;
 if ListBox.Style in [lbVirtual, lbVirtualOwnerDraw] then exit;
 Result := SendMessage(ListBox.Handle, LB_ADDSTRING, 0, Longint(PChar(S)));
 if Result < 0 then raise EOutOfResources.Create(SInsertLineError);
end;


Проверка:
procedure TForm24.Button1Click(Sender: TObject);
var
 i: integer;
 S, A, B, C: String;
begin
 S :=  "Просто достточно длинная строка символов для проверки алгоритмя работы" + IntToStr(GetTickCount);
 for i := 0 to 3000 do
   ListBox1.Items.Add(S);
 A := S;
 B := S;
 C := S;
 ShowMessage(IntToStr(DWORD(Pointer(DWORD(Pointer(S)) - 8)^)));
end;


Что и требовалось доказать :)


 
Игорь Шевченко ©   (2007-01-24 12:38) [5]

Rouse_ ©   (24.01.07 11:58) [4]

А ты подумай, с чего ей дублироваться ?


 
clickmaker ©   (2007-01-24 12:43) [6]


> [4] Rouse_ ©   (24.01.07 11:58)

lParam
Pointer to the null-terminated string that is to be added.
If you create the list box with an owner-drawn style but without the LBS_HASSTRINGS style, this parameter is stored as item data instead of the string to which it would otherwise point

указатель это. Откуда там возьмется дубль?


 
clickmaker ©   (2007-01-24 12:52) [7]

хотя...
LBS_HASSTRINGS
Specifies that a list box contains items consisting of strings. The list box maintains the memory and addresses for the strings

то есть, он копирует строки к себе?
тогда дубль, да


 
Rouse_ ©   (2007-01-24 13:09) [8]


> А ты подумай, с чего ей дублироваться ?


> то есть, он копирует строки к себе?

Да копирует, для оптимизации добавления большого кол-ва строк есть даже сообщение LB_INITSTORAGE


 
Rouse_ ©   (2007-01-24 13:14) [9]

Проверка №2, для неверующих:

procedure TForm24.Button1Click(Sender: TObject);
var
 i, d: integer;
 S: String;
begin
 S :=  "Просто достточно длинная строка символов для проверки алгоритмя работы" + IntToStr(GetTickCount);
 for i := 0 to 3000 do
   ListBox1.Items.Add(S);
 d := 32;
 for i := 0 to 69 do
   Move(d, Pointer(DWORD(Pointer(S)) + I)^, 1);
 ShowMessage(S);
 S := ListBox1.Items.Strings[1];
 ShowMessage(S);
end;


 
Rouse_ ©   (2007-01-24 13:16) [10]

Даже вот так лучше и наглядней:

procedure TForm24.Button1Click(Sender: TObject);
var
 i, d: integer;
 S, A: String;
begin
 S :=  "Просто достточно длинная строка символов для проверки алгоритмя работы" + IntToStr(GetTickCount);
 for i := 0 to 3000 do
   ListBox1.Items.Add(S);
 d := 32;
 A := S;
 for i := 0 to 69 do
   Move(d, Pointer(DWORD(Pointer(S)) + I)^, 1);
 ShowMessage(S);
 ShowMessage(A);
 S := ListBox1.Items.Strings[1];
 ShowMessage(S);
end;


 
Игорь Шевченко ©   (2007-01-24 13:37) [11]

Rouse_ ©   (24.01.07 13:16) [10]

А чего твой код-то показывает ?


 
Rouse_ ©   (2007-01-24 13:40) [12]

1. добавляем строки в ListBox
2. присваиваем строку другой переменной (в этот момент они указывают на один и тот же буффер)
3. пишем в этот буффер пробелы, чтобы небыло вызова UniqueStr
4. проверяем - обе переменных читающие с этого буффера показывают наличие пробелов
5. еслибы в listBox были тоже указатели, то последний ShowMessage(S) показал бытоже, что и ShowMessage(A)
6. А показывается полная строка.
7. вопрос, откуда берется эта полная оригинальная строка, если буффер. который ее хранил затерт пробелами...?


 
Игорь Шевченко ©   (2007-01-24 13:52) [13]

Rouse_ ©   (24.01.07 13:40) [12]

Теперь попробоуй свой код с ListBox, у которого стиль позволяет хранить пользовательские строки. Интересно.


 
Rouse_ ©   (2007-01-24 13:56) [14]

Вот если стиль стоит lbVirtual у listBox, тогда все нормально все три ShowMessage показывают наличие пробелов. По умолчанию же стоит стиль lbStandard, который именно копирует


 
Альф   (2007-01-24 15:05) [15]

Большое спасибо всем кто учавствовал в обсуждении.

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

Шаг 1:
Запускаем програмку.
Размер виртуальной памяти процесса в диспетчере задач = 848К

Шаг 2:
Вызываем эту процедуру -  размер памяти = 7 240К

var
 astr: array of string;

procedure T_main.Button5Click(Sender: TObject);
const
 S_1 = " - Просто досточно длинная строка символов для проверки алгоритма работы";
var
 i: integer;
begin
 Button5.Enabled := false;
 SetLength(astr, High(word));
 for i := Low(astr) to High(astr) do begin
   astr[i] := IntToStr(i) + S_1 + IntToStr(Random(i));
 end;
 Sleep(500);
 Button5.Enabled := true;
end;


Проверяем на калькуляторе примерный размер: 90*65534 =  около 6М.
Не точно - но очень похоже.

Шаг 2:
Заполняем ListBox1.
Процедура выполняется достаточно долго - результирующий размер памяти = 19 860К :(
Прирост еще в 12М ??? Судя по всему - или добавляется две копии - или же все строки переводяться в Unicode.


procedure T_main.Button6Click(Sender: TObject);
var
 i: integer;
begin
 Button6.Enabled := false;
 ListBox1.Items.BeginUpdate();
 for i := Low(astr) to High(astr) do begin
   ListBox1.Items.Add(astr[i]);
 end;
 ListBox1.Items.EndUpdate();
 Sleep(500);
 Button6.Enabled := true;
end;


Еще раз повторюсь - процедура работает в несколько раз дольше чем первая.

Шаг 3:
Чистим ListBox

 ListBox1.Clear();
 
Размер виртуалки практически возвратился к исходному и = 7 304К


 
Игорь Шевченко ©   (2007-01-24 17:35) [16]

Альф   (24.01.07 15:05) [15]

Разумеется, строки переводятся в Unicode, если ListBox их хранит
Но зачем отображать в listBox 65 тысяч строк в стандартном режиме - мания такая, да ? Пусть нашим пользователям будет хуже ?



Страницы: 1 вся ветка

Текущий архив: 2007.03.18;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.052 c
3-1166606026
Ilg
2006-12-20 12:13
2007.03.18
Текстовая БД и русские символы


15-1171879230
Juice
2007-02-19 13:00
2007.03.18
Компонента прямой записи в xls


9-1145623480
KiberKot
2006-04-21 16:44
2007.03.18
Анимация


1-1169444577
lenka_per
2007-01-22 08:42
2007.03.18
ячейка из excel больше 255 символов


15-1171890958
TIF
2007-02-19 16:15
2007.03.18
Оцените работу WEB-дизайнера (меня то есть :-)