Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > глюк с массивом


Автор: Scrip 24.5.2004, 15:37
Почему при выполнении этой процедуры
Код
procedure TForm1.Button1Click(Sender: TObject);
var x: array [0..10] of integer;;
begin
Edit1.Text:=inttostr(x[4]);
end;

x[4]=512?
При увеличении или уменьшении границ массива значение х[4] меняется.

Автор: Kesh 24.5.2004, 17:34
А что значит увеличение/уменьшение границ массива? У тебя статический массив, как можно в нем менять границы?

Вот если было бы
Код
var x: array of integer;

Тогда при SetLength(X,Size) было бы изменение границ массива, а где оно у тебя, я не вижу...

А значение содержимого массива у тебя будет меняться каждый раз при вызове TForm1.Button1Click, т.к. массив будет инициализироваться заново... Как решение - вынести массив из процедуры...

А вообще приведи больше кода... А то по этому куску я лично мало чего понял...

Хотя, наверное, это я такой непонятливый...

Автор: Pakshin A. S. 24.5.2004, 19:30
А где происходит заполение?! hehe.gif

Поставь полный код с заполнением, изменением и т. п. А то получается, что ты выводишь элемент, которого нет, либо в котором содержится число из пямяти, на чьё место был поставлен массив и которое не было удалено предыдущей программой, использующей данную ячейку памяти.

Автор: p0s0l 24.5.2004, 19:58
Это потому что массив - локальный, он хранится в стеке. Видимо мусор в стеке получается одинаковый (т.к. выполняются одни и те же действия).
Можешь увеличить, например, на единицу и длину массива, и № выводимого элемента, тогда у тебя x[5] тоже должно остаться 512...

Автор: Marriage 24.5.2004, 21:56
x[5] тоже должно остаться 512...


Действительно так ...
Нам преподавали, что массивы нужно обнулять перед использованием, так как в них изначально храняться каки-то значения ..

Автор: Jey_k 24.5.2004, 22:08
Marriage
конечно хранятся!!!!!
Это же просто выделенная область памяти и в ней что-нибудь да содержится при работе под виндами по крайней мере.
Если переменная или элемент массива работает как аккумулятор, то нужно обнулить сначала, в других случаях присвоить конкретное значение

Автор: Kesh 24.5.2004, 22:41
Вот это дискуссию развели!!! Scrip, чего молчишь... Народ требует код...

Автор: p0s0l 24.5.2004, 22:59
Kesh, он же привел код ?! Самый первый пост...

Автор: Kesh 24.5.2004, 23:02
p0s0l Смотри мой первый пост в этой теме... Я просил больше кода... Да и не я один... Просто из вопроса я многого не понял...

Автор: December 25.5.2004, 00:48
p0s0l
Цитата
он же привел код ?! Самый первый пост..

На самом деле трудно поверить, что это весь код smile.gif Переросли smile.gif

Автор: p0s0l 25.5.2004, 01:01
December, Kesh, и др.
Выразю вопрос Scrip'а в понятной всем форме, а то многие требуют какой-то код...
Итак, вопрошаю:
Если изменить границы массива, т.е. вместо:
var x: array [0..10] of integer;
поставить, к примеру,
var x: array [0..15] of integer;
то по какой-то неведомой причине четвертый элемент массива не изменится... Что за причина такая ?
(PS: массив - локальный, т.е. без начального значения).

Какой еще код нужен ? Он привел более, чем достаточно...

Автор: Kesh 25.5.2004, 01:07
p0s0l Дык изменится... И при каждом вызове процедуры (читай - инициализации локального статического массива) будет новый... В зависимости от выделяемого куска памяти... А вот с динамическими все так...

Код
// пример для консоли
var
 a: array of integer;
begin
 SetLength(a,2);
 a[0] := 1;
 a[1] := 3;
 SetLength(a,4);
 a[2] := 2;
 a[3] := 5;
 Write(a[1]); // отгадай что выдаст... я думаю '3'
end

Добавлено @ 01:08
Или я опять чего-то не понял...

Автор: p0s0l 25.5.2004, 01:39
Kesh, а ты проверь. Не изменится. Потому что нет никакой инициализации. Просто в стеке выделяется память (add esp, -40h к примеру - на 16 integer'ов). Ну буди если ты будешь кучу push'ов делать (или действия, приводящие к записи в стек), чтобы забить стек, перед вызовом этой процедуры, тогда да - изменится...
А про динамические - вообще не то... Уж не знаю, как и объяснять...

Автор: Scrip 25.5.2004, 11:05
p0s0l, благодарю!!!

Автор: Kesh 25.5.2004, 11:13
Цитата
To truncate a dynamic array, pass it to SetLength or Copy and assign the result back to the array variable. (The SetLength procedure is usually faster.) For example, if A is a dynamic array, A := SetLength(A, 0, 20) truncates all but the first 20 elements of A.
Help из D6... Именно по этому я и говорю, что при изменении размеров динамических массивов значения в незатронутых элементах остаются без изменения...
А про статику ты и сам сказал
Цитата
Ну буди если ты будешь кучу push'ов делать (или действия, приводящие к записи в стек), чтобы забить стек, перед вызовом этой процедуры, тогда да - изменится...
Ага буду...

Автор: Scrip 25.5.2004, 11:29
Цитата
Нам преподавали, что массивы нужно обнулять перед использованием

Что значит обнулять? Так что-ли? biggrin.gif Или я не так понял?
Код
var a: array [1..10] of integer;
i: integer;
begin
for i:= low(a) to high(a) do
a[i]:=0;
end;


Автор: Kesh 25.5.2004, 11:31
Ага... именно так...

Автор: Akella 27.5.2004, 17:31
А нельзя ли вместо обнуления, удалить его, а затем создать заново thumbs-up.gif

Автор: Scrip 27.5.2004, 19:25
dsergey
Нееее, не получится, мы ведь ничего в этом случае не записываем в ячейки памяти, а значит весь мусор там по прежнему остается.

Автор: Scrip 27.5.2004, 20:09
А вот ешо один и один воп.
1. Почему если массив а объявить как фактичесий, то во всех элементах массива будет 0, а если как формальный(т.е внутри подпрограммы) то с мусором. sad.gif //только щас заметил
2. Присвоил а[4] какое-нибудь значение.
Код
procedure TForm1.Button1Click(Sender: TObject);
var a: array [1..10] of integer;
begin
a[4]:=2323;
Edit1.Text:=inttostr(a[4]);
end;

В edit1 появляется, естественно, 2323. Далее, если удалить строку a[4]:=2323 и запустить прогу занова, то в edit1 появл. опять 512. Почему? Может какая нить прога туда забивает 512. Но если эта прога уже заняла эту область памяти, тогда как туда залазит Delphi? Что-то я опят недопонимаю.

Автор: Girder 27.5.2004, 23:05
Попробую попроще объяснить:

Для хранения твоих значений используется стек.
т.е.
push ebp
mov ebp,esp
add esp,-$30 - резервируется стек под твой массив
....

Отступление:
1) Когда заносится информация в стек командой "push ..." - процессор уменьшает адресс стека
(на необходимое количество значений) и записывает по получившимуся адресу информацию.
2) Когда информация забирается(выгружается) из стека командой "pop ..." - процессор копирует
информацию из стека(туда куда укажеш) и увеличивает(на необходимое количество значений) адресс стека,
exclamation.gif НО... - не обнуляет(очищает) информацию в стеке.

Мысля пошла?... Нет, тогда продолжаем.

1)Так как используется стек, то этот адресс(а[4]), в стеке, уже наверняка был использован в твой
программе(хочеш ты этого или нет) и было записано в него 512.
2)если напишеш вот так:
Код

 procedure TForm1.Button1Click(Sender: TObject);
 var a: array [1..10] of integer;
 begin
  Info_ESP;
 end;

 procedure TForm1.Info_ESP;
 var a: array [1..10] of integer;
 begin
   Edit1.Text:=inttostr(a[4]);
 end;

То уже не получиш 512.
3) exclamation.gif Если скомпилируеш не в D7, а в D5,D6 ... exclamation.gif
То уже не получиш 512.
4)если напишеш вот так:
Код

 procedure TForm1.Button1Click(Sender: TObject);
 var b: array [1..10] of integer;
      a: array [1..10] of integer;
 begin
  Edit1.Text:=inttostr(a[4]);
  Edit2.Text:=inttostr(b[4]);
 end;

то а[4]<>512, а b[4]=512

exclamation.gif exclamation.gif exclamation.gif
Компилятор используется один и тот же, так? ... Так.
Стек резирвируется рядом(add esp,-$30), так? ... Так.
Большая вероятность(>90%) что данный адресс в стеке(который выделяется под a[4]) был
использован в участке кода, exclamation.gif твоей программы exclamation.gif , которая передает
управление Button1Click - сам понимаеш данный участок будет менятся как правило при
изменении компилятора.

Т.ч. не грузись - все так как должно быть, а иначе быть не может.

Автор: Scrip 28.5.2004, 00:58
Идею понял.
А вот с этим желательно поподробней.
Код
push ebp
mov ebp,esp
add esp,-$30 - резервируется стек под твой массив

______________________________________________________
кстати,Girder, ты как узнал, что у меня D7.

Автор: Girder 28.5.2004, 08:29
Я же написал волшебное слово - компилятор.
Просто проверил в какой версии выдается 512

Цитата
А вот с этим желательно поподробней

- Всмысле?

Автор: Scrip 28.5.2004, 11:13
Да не знаю я что такое
Код
push ebp
mov ebp,esp
add esp,-$30
wink.gif

Автор: Girder 28.5.2004, 11:56
А... ты об этом.

Не грузись пока.
Придет время -поймеш

Удачи.

Автор: Akella 28.5.2004, 12:16
Неверное, с Delphi8 уже не поймешь. Там нет asm

Автор: Jey_k 30.5.2004, 20:44
Цитата(dsergey @ 28.5.2004, 12:16)
Неверное, с Delphi8 уже не поймешь. Там нет asm

Серьезно? Ну и отстой...
Добавлено @ 20:48
Цитата(Scrip @ 27.5.2004, 20:09)
Но если эта прога уже заняла эту область памяти, тогда как туда залазит Delphi? Что-то я опят недопонимаю.

Запомни и детям передай:
Только в одной операционной системе прога адресует только выделенную ЕЙ память а не весь доступный объем- это OS/2.
А в форточках возможно все, поэтому, переменные, элементы массивов и даже строк лучше либо сразу забивать значениями, либо если они, например, автоинкрементные или используют другие способы автоизменений, обнулять.
Успехов smile.gif

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)