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

Вниз

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

 
Германн ©   (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;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.01 c
15-1308555247
DiamondShark
2011-06-20 11:34
2011.10.16
А вы в компьютерах разбираетесь?


2-1308849951
Pcrepair
2011-06-23 21:25
2011.10.16
ИНДИ10, вопросы по синтаксису клиента


15-1308767885
alexdn
2011-06-22 22:38
2011.10.16
Шаблон для ms sql


2-1308890972
Wryyyyyy
2011-06-24 08:49
2011.10.16
Query.Parameters


15-1308503421
alexdn
2011-06-19 21:10
2011.10.16
9-й эксплорер