Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2011.10.16;
Скачать: [xml.tar.bz2];

Вниз

Ошибка при удалении контролов   Найти похожие ветки 

 
Германн ©   (2011-06-23 02:52) [0]

Вот впервые в моей практике "стабильно" получаю AV в "стабильной" строке кода "стабильно в некотором моменте рантайма" и не могу понять причину.
Строка кода где случается сей AV такова:
 for i:=sPanel1.ControlCount-1 downto 0 do sPanel1.Controls[i].Free;
Сообщение об ошибке такое: Access violation at address 005E6EA3 in module "ХХХ.exe". Read of address 00000024

Суть кода - удалить все имеющиеся контролы на панели, чтобы пользователь мог создать другие.
Продолжение задачи http://delphimaster.net/view/2-1308354496/


 
KilkennyCat ©   (2011-06-23 03:42) [1]

а:=sPanel1.ControlCount-1;
for i:=а downto 0 do sPanel1.Controls[i].Free;


 
Германн ©   (2011-06-23 04:09) [2]


> KilkennyCat ©   (23.06.11 03:42) [1]
>
> а:=sPanel1.ControlCount-1;
> for i:=а downto 0 do sPanel1.Controls[i].Free;

Хм. Именно такой код я и привел в вопросе.
Наскоко я вообще знаю и понимаю Дельфи.


 
KilkennyCat ©   (2011-06-23 05:18) [3]

есть некоторая разница.
во-первых, нет постоянного вычисления sPanel1.ControlCount-1.
во-вторых (но тут я могу ошибаться) ав может возникать из-за того, что sPanel1.ControlCount-1 при очередном вычислении может вернуть индекс объекта, находящегося в процессе удаления, а потом ему еще раз фрии...


 
Ega23 ©   (2011-06-23 08:18) [4]


> KilkennyCat ©   (23.06.11 05:18) [3]


Костя, не позорься.


> Строка кода где случается сей AV такова:
>  for i:=sPanel1.ControlCount-1 downto 0 do sPanel1.Controls[i].
> Free;


Controls - это то, для чего Parent. Components - для чего Owner.
Создавай контролы с Owner = Panel, очищай -
for i:= panel.ComponentCount - 1 downto 0 do

НУ и эта... Ошибка может быть совсем не в этом. :) Что CallStack говорит?


 
BoB   (2011-06-23 09:14) [5]

Хм..
А у меня и [0] и [1] без проблем.
Контролы : три батона и три лабеля, созданы в дезайнтаме (D7)
Так что (ИМХО)
[4] "Ошибка может быть совсем не в этом."


 
Anatoly Podgoretsky ©   (2011-06-23 09:34) [6]

Похоже, что sPanel1 равно nil
Восспользуйся отладчиком и посмотри значение.


 
RWolf ©   (2011-06-23 09:52) [7]

думается мне, что проблема в смешении сущностей Components[] (те компоненты, за чьё удаление отвечает контейнер при собственном удалении) и Controls[] (контролы, которые он должен показывать внутри собственного окна).
а именно, в том, что в приведённом примере что-то из содержимого удаляется автоматом по два раза.


 
KilkennyCat ©   (2011-06-23 10:08) [8]


> Ega23 ©   (23.06.11 08:18) [4]

а в чем именно я ошибся?


 
Ega23 ©   (2011-06-23 10:33) [9]


> а в чем именно я ошибся?

в "во-первых".


 
Alex_C   (2011-06-23 10:42) [10]

Ошибка есть :)
Ошибка в том, какие элементы таким способом удадяешь.
Предлагаю все сделать следующий эксперимент и удивиться:
делаете проект с формой и панелью. На нее поочередности наносите элементы и удаляете их. Все будет нормально до тех пор, пока на форме не появится TLabeledEdit - при попытке его удалить возникнет AV.


 
sniknik ©   (2011-06-23 10:44) [11]

> а в чем именно я ошибся?
значения для for вычисляются 1 раз.

а работает?
with sPanel1 do while ControlCount > 0 do Controls[0].Free;

> Ошибка может быть совсем не в этом
а, например в том, что в деструкторе 100 контрола есть Free/дестрой для 17-го...


 
Ega23 ©   (2011-06-23 10:54) [12]


> делаете проект с формой и панелью. На нее поочередности
> наносите элементы и удаляете их. Все будет нормально до
> тех пор, пока на форме не появится TLabeledEdit - при попытке
> его удалить возникнет AV.


unit Unit18;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls;

type
 TForm18 = class(TForm)
   Panel1: TPanel;
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form18: TForm18;

implementation

{$R *.dfm}

procedure TForm18.Button1Click(Sender: TObject);
var
 i: Integer;
begin
 for i := Panel1.ComponentCount - 1 downto 0 do
   Panel1.Components[i].Free;

end;

procedure TForm18.FormCreate(Sender: TObject);
begin
 with TLabeledEdit.Create(Panel1) do
 begin
   SetBounds(10, 10, 100, 100);
   Parent := Panel1;
 end;
end;

end.


Никаких AV. ЧЯДНТ?


 
Alex_C   (2011-06-23 10:56) [13]

А у меня стабильная ошибка. Перед тем как написать специально несколько раз проверил....
Delphi 7


 
Ega23 ©   (2011-06-23 10:57) [14]


> А у меня стабильная ошибка. Перед тем как написать специально
> несколько раз проверил....


Код в студию.


 
Alex_C   (2011-06-23 10:58) [15]

Причем как я уже написал - только на TLabeledEdit (это ж как бы 2 контрола - может в этом проблема?) Сдается мне что может быть это конкретно проблема 7 Дельфи.


 
Alex_C   (2011-06-23 11:00) [16]


> Код в студию.


А никакого кода нет :)
Я ж написал - просто на панель в Дельфи набросал кучу разных кампонент. И удалял их по нажатию на кнопку. Все компоненты, кроме TLabeledEdit удалялись без проблем. В реал-тайме я их не создавал.


 
Ega23 ©   (2011-06-23 11:04) [17]


> (это ж как бы 2 контрола - может в этом проблема?


Не должно быть никакой проблемы.


 
Ega23 ©   (2011-06-23 11:05) [18]

Попробую спецом дома D7 поставить и проверить. Но это только вечером.


 
sniknik ©   (2011-06-23 11:13) [19]

> А у меня стабильная ошибка. Перед тем как написать специально несколько раз проверил....
> Delphi 7
sniknik ©   (23.06.11 10:44) [11]


 
Rouse_ ©   (2011-06-23 11:32) [20]


> KilkennyCat ©   (23.06.11 05:18) [3]
> есть некоторая разница.
> во-первых, нет постоянного вычисления sPanel1.ControlCount-1

Костик, ты чего, перегрелся? :)
Это-ж не WHILE и не REPEAT цикл, а FOR, в котором начальное и конечное значение итератора рассчитываются только один раз :)


 
KilkennyCat ©   (2011-06-23 11:39) [21]

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


 
Rouse_ ©   (2011-06-23 11:44) [22]

ЗЫ: а вообще дело в том что TLabeledEdit состоит из двух контролов, поэтому при вызове Free разрушаются оба и соответственно позиция итератора не соответствует оставшемуся количеству контролов.
Посему правильный вариант:
 while Panel1.ControlCount <> 0 do
   Panel1.Controls[0].Free;


 
sniknik ©   (2011-06-23 11:47) [23]

> Посему правильный вариант:
- доктор меня все игнорируют.
- следующий!


 
Alex_C   (2011-06-23 11:48) [24]


> TLabeledEdit состоит из двух контролов


Собственно о чем я и писал.


> Посему правильный вариант:


+1!


 
Rouse_ ©   (2011-06-23 12:07) [25]

точнее еще более правильный вот так:
while Panel1.ControlCount <> 0 do
  Panel1.Controls[Panel1.ControlCount - 1].Free;

дабы List не ресортился при каждом удалении нулевого элемента, а просто отсекался с хвоста ;)


 
Ega23 ©   (2011-06-23 12:08) [26]


> Посему правильный вариант:
>  while Panel1.ControlCount <> 0 do
>    Panel1.Controls[0].Free;


Это в том случае, если ты хочешь удалить и те контролы, что были созданы в дизайн-тайм, и те, что в ран-тайм.
А вот если ты их все создаёшь в ран-тайм с Owner=Panel1, а потом грохаешь либо Panel1 целиком, либо проходишь по Panel1.ComponentCount-1 downto 0, то никакого AV не будет.


 
Ega23 ©   (2011-06-23 12:09) [27]


> точнее еще более правильный вот так:

Тоже вариант.


 
Омлет ©   (2011-06-23 12:14) [28]

> Ega23 ©   (23.06.11 12:08) [26]
> А вот если ты их все создаёшь в ран-тайм


Тогда лучше ссылки на них хранить в отдельном массиве и не иметь никаких проблем.


 
Ega23 ©   (2011-06-23 12:29) [29]


> Тогда лучше ссылки на них хранить в отдельном массиве и
> не иметь никаких проблем.


А зачем лишнюю сущность заводить, если уже TComponent.FComponents: TList есть?
Впрочем, это философский вопрос.


 
sniknik ©   (2011-06-23 12:37) [30]

> дабы List не ресортился при каждом удалении нулевого элемента, а просто отсекался с хвоста ;)
пофиг. в вызове RemoveControl все одно есть ресорт, с какого конца не удаляй. а без него, ибез ресорта (код из TWinControl.Destroy;)
 I := ControlCount;
 while I <> 0 do
 begin
   Instance := Controls[I - 1];
   Remove(Instance);
   Instance.Destroy;
   I := ControlCount;
 end;
, должен быть доступ к приватному методу.


 
Омлет ©   (2011-06-23 12:48) [31]

> А зачем лишнюю сущность заводить, если уже TComponent.FComponents: TList есть?

Только вот к Panel1.Controls он отношения не имеет )


 
Юрий Зотов ©   (2011-06-23 13:54) [32]

> Ega23 ©   (23.06.11 12:29) [29]
> А зачем лишнюю сущность заводить, если уже
> TComponent.FComponents:  TList есть?

Насколько помню, у него к этой панели еще и меню привязано, через Owner. Правда, непонятно зачем - но это уже другой вопрос.


 
Ega23 ©   (2011-06-23 14:02) [33]


> Насколько помню, у него к этой панели еще и меню привязано,
>  через Owner. Правда, непонятно зачем - но это уже другой
> вопрос.


Не, ну тогда вообще отдельный компонент имеет смысл делать. ИМХО. Тогда уже точно никаких непоняток не будет - накидал что надо, ссылки сохранил как Омлет в [28] предложил. И делай что хочешь.


 
Германн ©   (2011-06-24 01:59) [34]

Вчера три раза подряд получил сие AV выполняя одни и те же действия.
Сегодня как не стараюсь, не получаю AV.
Ну я понимаю, что AV это такая "гадость", которая может проявляться (и это плюс), а может и не проявляться.
У меня только один "вопрос неуча". А то что я удаляю Контролы методом
Controls[i].Free может как-то влиять?
Т.е. не нужно ли мне вызывать метод Free реального контрола?


 
Омлет ©   (2011-06-24 08:22) [35]

> Т.е. не нужно ли мне вызывать метод Free реального контрола?

Ты его и вызываешь.


 
Ega23 ©   (2011-06-24 10:08) [36]


> А то что я удаляю Контролы методом
> Controls[i].Free может как-то влиять?


Ты чё, ветку не прочитал? По-моему, уже все возможные варианты перебрали, не?


 
Anatoly Podgoretsky ©   (2011-06-24 10:54) [37]

> Германн  (24.06.2011 01:59:34)  [34]

Ты и так вызываешь методы реального объекта
к просто сказал сделать,
сделано.


 
Германн ©   (2011-06-25 02:02) [38]


> Омлет ©   (24.06.11 08:22) [35]
>
> > Т.е. не нужно ли мне вызывать метод Free реального контрола?
>
>
> Ты его и вызываешь.
>


> Ega23 ©   (24.06.11 10:08) [36]
>
>
> > А то что я удаляю Контролы методом
> > Controls[i].Free может как-то влиять?
>
>
> Ты чё, ветку не прочитал? По-моему, уже все возможные варианты
> перебрали, не?
>


> Anatoly Podgoretsky ©   (24.06.11 10:54) [37]
>
> > Германн  (24.06.2011 01:59:34)  [34]
>
> Ты и так вызываешь методы реального объекта
> к просто сказал сделать,
> сделано.
>

Наверно у меня вчера была "нелетная погода". И в результате я грешил на "непогрешимые основы".


 
Германн ©   (2011-06-25 02:02) [39]


> Омлет ©   (24.06.11 08:22) [35]
>
> > Т.е. не нужно ли мне вызывать метод Free реального контрола?
>
>
> Ты его и вызываешь.
>


> Ega23 ©   (24.06.11 10:08) [36]
>
>
> > А то что я удаляю Контролы методом
> > Controls[i].Free может как-то влиять?
>
>
> Ты чё, ветку не прочитал? По-моему, уже все возможные варианты
> перебрали, не?
>


> Anatoly Podgoretsky ©   (24.06.11 10:54) [37]
>
> > Германн  (24.06.2011 01:59:34)  [34]
>
> Ты и так вызываешь методы реального объекта
> к просто сказал сделать,
> сделано.
>

Наверно у меня вчера была "нелетная погода". И в результате я грешил на "непогрешимые основы".



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

Форум: "Начинающим";
Текущий архив: 2011.10.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.004 c
2-1308936747
vegarulez
2011-06-24 21:32
2011.10.16
как правильно вставить декларацию процедуры?


15-1308742325
>|<
2011-06-22 15:32
2011.10.16
Печать наклейки на USB-принтере


15-1308891816
Дмитрий С
2011-06-24 09:03
2011.10.16
Как назначить клавиши на кнопки Back/Forward в IDE?


6-1243319342
kunka
2009-05-26 10:29
2011.10.16
vpn


15-1308062128
Мимо не прошел
2011-06-14 18:35
2011.10.16
Свое





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский