Главная страница
    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.49 MB
Время: 0.037 c
2-1172159524
Dennis Pakseew
2007-02-22 18:52
2007.03.18
Как сделать кнопку объемной?


15-1172095241
ProgRAMmer Dimonych
2007-02-22 01:00
2007.03.18
Извините за наглость, но


2-1172274829
koha
2007-02-24 02:53
2007.03.18
Клик мышью в TListView


2-1172603027
sat
2007-02-27 22:03
2007.03.18
TMemoryStream


15-1172238460
chvank
2007-02-23 16:47
2007.03.18
Геометрию изменил, гад, что делать?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский