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

Вниз

Очистить массив из Integer-ов   Найти похожие ветки 

 
Dmitry_177   (2007-03-30 09:22) [0]

есть массив из Integer-ов.. Мне его надо очистить, делаю FillChar, чтобы заполнить его нулями.. И почему-то после этого если како-му то его элементу что-то присвоить, то будет ошибка AV. Вот так выскакивает AV:

var
 Codes: array of Integer;

procedure TForm1.Button1Click(Sender: TObject);
begin
 SetLength(Codes, 1);
 FillChar(Codes, SizeOf(Codes), 0);
 Codes[0] := 212;
 MessageBox(0, PChar(IntToStr(Codes[0])), "", 0);
end;

На строке Codes[0] := 212;

Подскажите пожалуста почему так?


 
ЮЮ ©   (2007-03-30 09:29) [1]

FillChar(Codes, SizeOf(Codes), 0);
зачем тут обнулять, если выделяешь 1 элемент и тут же его записываешь

SizeOf(Codes) не имеет никакого отношения к размеру памяти, занятой Codes, это указатель на область памяти. По этой же причине, нельзя указывать Codes первым параметром, надо Codes[0];

Имхо, достаточно
Codes := nil;
перед новым наращиванием массива
SetLength(Codes, 1);


 
TRUNK ©   (2007-03-30 09:32) [2]


> Dmitry_177   (30.03.07 09:22)
> Подскажите пожалуста почему так?

Потому что массив динамический, и Codes на самом деле содержит указатель на массив. Поэтому FillChar обнуляет указатель, что равноценно Codes := nil, поэтому и последующее обращение к массиву вызывает AV.


 
begin...end ©   (2007-03-30 09:37) [3]

Потому что переменная, имеющая тип "динамический массив", по сути является указателем на тело массива, т.е. содержит адрес его первого (нулевого) элемента. Следовательно, в строке с FillChar Вы записываете нули не в тело массива, а в указатель на него. В результате ссылка портится -- теперь вместо реального адреса тела массива она содержит ноль. Поэтому дальнейшая попытка записи в массив с использованием этой ссылки приводит к AV -- ведь фактически Вы пытаетесь записать что-то по нулевому адресу, а чтение и запись из памяти / в память по такому адресу запрещены.

Чтобы правильно очистить такой массив, нужно строку с FillChar переписать так: FillChar(Codes[0], sizeof(Codes[0]) * Length(Codes), 0).

Однако, если речь идёт об очистке массива array of integer, только что инициализированного первым вызовом SetLength (как в приведённом примере), то это лишнее -- все элементы такого нового массива вначале содержат ноль.


 
Dmitry_177   (2007-03-30 09:40) [4]


> зачем тут обнулять, если выделяешь 1 элемент и тут же его
> записываешь

Это я к примеру же привел.. А мне надо к примеру выделить 100 элементов, и какие-то из них заполнить, а остальные что были нулями.. Вот я и подумал о том, что если выделить 100 элементов SetLength-ем, как бы там мусора небыло, чтобы не оказалось что какой-то элемент уже чему-то равен, вот и решил обнулять..


 
SergGG ©   (2007-03-30 09:47) [5]

>Dmitry_177   (30.03.07 09:22)
Если тебе нужно использовать FillChar...

Type
TCodes= Integer;
PCodes=^TCodes;

procedure TForm1.Button1Click(Sender: TObject);
var Codes:PCodes;
begin
GetMem(Codes, SizeOf(TCodes));
FillChar(Codes^, SizeOf(Codes), 0);
Codes^ := 212;
MessageBox(0, PChar(IntToStr(Codes^)), "", 0);
FreeMem(Codes, SizeOf(TCodes));
end;


 
Ketmar ©   (2007-03-30 12:21) [6]

на кол. что, справку отменили? там по dynamic arrays весьма немало текста... кажыдцо, пора опять мётлы раздавать... %-((


 
Dmitry_177   (2007-03-30 14:42) [7]

Мы ведиляем под массив память: SetLength(Codes, 1); а когда массив уже становится ненужным нужно ли освобождать память, которая была под него выделена? Как-нибудь так: FreeMem(Codes); ???


 
SergGG ©   (2007-03-30 15:01) [8]

>SetLength(Codes, 1) .... FreeMem(Codes); ???
Их нельзя связать.
См. [5]. Там нет SetLength


 
Loginov Dmitry ©   (2007-03-30 18:58) [9]

> Мы ведиляем под массив память: SetLength(Codes, 1); а когда
> массив уже становится ненужным нужно ли освобождать память,
> которая была под него выделена?


Как хочешь. Можешь освобождать, а можешь и не освобожать. Для освобождения памяти следует сделать следующее:
Code := nil;


 
Dmitry_177   (2007-04-02 11:17) [10]

А как можно из такого массива удалить какойнибудь элемент? Например будет он состоять из 5 элементов, а удалить к примеру 3?


 
Asail   (2007-04-02 11:33) [11]

ИМХО Никак.
Только смещением (т.е. 4-й в 3-й и 5-й в 4-й и т.д., потом SetLength(n-1))


 
VEZ   (2007-04-02 17:54) [12]


> А как можно из такого массива удалить какойнибудь элемент?
>  Например будет он состоять из 5 элементов, а удалить к
> примеру 3?


Имхо так

procedure TForm2.Button1Click(Sender: TObject);
var
 a: array of Word;
 i: Integer;
begin
 SetLength(a, 5);
 Label1.Caption:= "";
 Label2.Caption:= "";
 for i := 0 to Length(a) - 1 do
 begin
   a[i]:= i;
   Label1.Caption:= Label1.Caption + IntToStr(a[i]) + " ";
 end;
 // Remove 3th element
 MoveMemory(@a[3], @a[4], (Length(a)-3) * SizeOf(Word));
 SetLength(a, 5-1);
 // element has removed
 for i := 0 to Length(a) - 1 do
   Label2.Caption:= Label2.Caption + IntToStr(a[i]) + " ";
end;


 
Dmitry_177   (2007-04-02 18:55) [13]

Мне тут подсказали еще лучше способ =)

//удалить i-й элемент массива

move(codes[i+1],codes[i],(length(codes)-i-1)*sizeof(integer));
setlength(codes,length(codes)-1);


 
Asail   (2007-04-02 20:47) [14]


> VEZ   (02.04.07 17:54) [12]

> Имхо так

Ну, я и говорю - смещением...


> Dmitry_177   (02.04.07 18:55) [13]
> Мне тут подсказали еще лучше способ =)


Чем лучший и по сравнению с каким? Тот-же способ, что у VEZ.


 
Dmitry_177   (2007-04-02 23:05) [15]

да, но этот ИМХО быстрей..


 
MsGuns ©   (2007-04-02 23:16) [16]

Буря в стакане блин, - прав Кетмарь, метлы нужны



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

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

Наверх




Память: 0.51 MB
Время: 0.046 c
15-1175187179
eXPell
2007-03-29 20:52
2007.04.22
Stack-overflow....


3-1170430978
s_t_d
2007-02-02 18:42
2007.04.22
QReport в Delphi 7. Как получить доступ к элементам?


2-1175196193
Riiid
2007-03-29 23:23
2007.04.22
Что в проекте испльзовал?


2-1175324426
Roman_S
2007-03-31 11:00
2007.04.22
Как найти на рабочем столе ярлык (НЕ по названию)?


1-1172676041
DenisNew
2007-02-28 18:20
2007.04.22
ширина закладки ttabsheet