Переключение на Главную Страницу Страницы: 1 2 [3] 4  ОтправитьПечать
Очень популярная тема (более 25 ответов) Создание элемента на форме (число прочтений - 23550 )
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Создание элемента на форме
Ответ #30 - 21. Февраля 2008 :: 18:27
Печать  
[b]orefkov[/b], [b]Uzhast[/b]

Знаете, а правда как всегда где-то посередине.

Я совершенно точно могу сказать про CBtnEdit, т.к. занимался последнюю неделю именно этой темой.
Это автоматический объект, с процедурой самоликвидации в CMaskEdit::PostNcDestroy.
[ecx+0x40] - это как раз флаг bAutoDestroy для этих объектов.

Так что освобождение объектов различных типов необходимо делать по-разному.
Для текста и кнопок, видимо, необходимо delete; для самоликвидирующихся объектов в иерархии CMaskEdit достаточно DestroyWindow().

P.S.

[b]orefkov[/b]

На самом деле, Саша, там не чистый FromHandlePermanent, a GetDescendantWindow(nID, FALSE), который может закончиться FromHandle и временным объектом.
Я какое-то время обдумывал, не в этом ли грабли, но оказалось что мои грабли - не в этом.

P.P.S.

Вот такая разгадка.
Пошел за еще одной банкой пива.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Создание элемента на форме
Ответ #31 - 21. Февраля 2008 :: 19:01
Печать  
Цитата:
Вот как раз если не делать delete, а DestroyWindow, и будут утечки памяти.
Поясню.
DestroyWindow не делает ничего, кроме как вызова этой же апишной функции, которая разрушает окно, но НЕ УНИЧТОЖАЕТ объект CWnd.
А по поводу двойного удаления - в данном случае 1С НЕ ХРАНИТ указатели на CWnd контролов, а когда нужно, дергает GetDlgItem с нужным ID, и по полученному HWND делает CWnd::FromHandlePermanent, чтобы получить CWnd*. Это и позволяет создав окно с тем же идшником, подменить атрибут формы, и как показала практика, 1С при убитии формы, удаляет именно объект CWnd нового, нами созданного окошка.


Очень взвешенное и подробное высказывание. Сказал бы спасибо, но проблема в том, что это высказывание совершенно не соответствует действительности.

По пунктам.

Цитата:
в данном случае 1С НЕ ХРАНИТ указатели на CWnd контролов

1С не хранит указатели на CWnd ТОЛЬКО в том случае, когда 1С не создает нетривиальных объектов CWnd. Во всех других случаях 1С ДОЛЖНА хранить подобные указатели потому, что MFC НЕ КОНТРОЛИРУЕТ время жизни объектов CWnd в случае, когда эти объекты были созданы не самой библиотекой MFC. Это происходит хотя бы потому, что объект CWnd может создаваться как на стеке, так и в хипе. MFC не может самостоятельно определить КАК уничтожать конкретный объект, если не знает, как он был порожден. Я думаю, не нужно пояснять, что нетривиальные объекты CWnd в 1С есть.

Цитата:
а когда нужно, дергает GetDlgItem с нужным ID, и по полученному HWND делает CWnd::FromHandlePermanent, чтобы получить CWnd*

Опять неверно. 1С вызывает CWnd::GetDescendantWindow. Туда она передает ID нужного элемента и в качестве параметра bOnlyPerm передает FALSE (!). Параметр FALSE означает, что будет вызван метод CWnd::FromHandle, а не CWnd::FromHandlePermanent.

Вывод. Если использовать delete pObject, то двойное удаление памяти будет ОБЯЗАТЕЛЬНО. Потому что возможно наличие двух видов объектов CWnd:
- Созданных самой 1С. Второе удаление при этом произойдет при разрушении формы, когда 1С будет подчищать объекты за собой.
- Временные объекты, созданные MFC. В этом случае второе удаление произойдет при первом же виндовом сообщении WM_ENTERIDLE - в этом случае MFC удалит все временные объекты CWnd, которые она удерживает в карте временных объектов.

PS. Когда я задавал исходный вопрос, я ожидал, что мне либо ответит грамотный в этих вопросах человек, либо вообще никто не ответит. Но я не ожидал, что мне будут сливать откровенную дезинформацию...
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Создание элемента на форме
Ответ #32 - 21. Февраля 2008 :: 19:05
Печать  
Если же вызывать DestroyWindow, то утечек памяти не возникнет:
- Если объект CWnd - объект 1С, то он будет удален средствами 1С либо при разрушении формы, либо в процессе обработки сообщения WM_DESTROY (как раскопал kms).

- Если объект CWnd - временный объект MFC, то он будет удален в обработке ожидания, когда MFC будет подчищать временные объекты.
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Создание элемента на форме
Ответ #33 - 21. Февраля 2008 :: 19:22
Печать  
[quote author=kms link=1199369336/30#30 date=1203618459][/quote]

Получается, благодаря твоим раскопкам, мое высказывание насчет ХРАНЕНИЯ указателей на объекты CWnd становится НЕ СОВСЕМ верным ;) Но главное, что я хотел сказать сохраняется - СУЩЕСТВУЮТ объекты, ВРЕМЯ ЖИЗНИ, которых контролирует сама 1С.
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Создание элемента на форме
Ответ #34 - 21. Февраля 2008 :: 19:54
Печать  
Э, кто тебе ластик дал? Ну-ка отдай! Подмигивание

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

По остальному: в #31 ты еще примерно на середине пути. Подмигивание
Если будет интересно, я тебе могу без эмоций нарисовать, что там по-правде происходит.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Создание элемента на форме
Ответ #35 - 21. Февраля 2008 :: 19:59
Печать  
kms писал(а) 21. Февраля 2008 :: 19:54:
Э, кто тебе ластик дал? Ну-ка отдай! Подмигивание




kms писал(а) 21. Февраля 2008 :: 19:54:
Насчет delete (про суслика, которого не видно, но он есть): конечно, 1С сам управляет временем жизни контолов.
Просто в моей задаче, если ты помнишь, мне приходится добавлять и удалять атрибуты на форму.
При этом я выполняю всю работу сам, и если я не сделаю delete там, где требуется delete, шансы, что это сделает кто-то еще равны нулю.

По остальному: в #31 ты еще примерно на середине пути. Подмигивание
Если будет интересно, я тебе могу без эмоций нарисовать, что там по-правде происходит.

Где эмоции?! Какие эмоции?! Не вижу никаких эмоций! Улыбка
Интересно, рассказывай.
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Создание элемента на форме
Ответ #36 - 21. Февраля 2008 :: 20:34
Печать  
Ну, схема комбинируется из описаний, данных разными авторами в предыдущих постах Улыбка

Короче, 1С действительно не хранит ссылок на CWnd.
Но тем не менее у нее есть массив CGetField*, а заодно и массив CGetCtrl*.
Впрочем, не суть, достаточно того, что она знает CtrlID этих окон.
При разрушении формы она проходит по списку CtrlID и как раз методом GetDescendantWindow/FromHandle получает CWnd*.
FromHandle может, конечно, возвращать CTempWnd, но как правило не возвращает, ибо существуют перманентные объекты, а у них приоритет.
Ну, дальше уничтожение объектов - дело техники.

В итоге получается такая картина:
Если delete текст или кнопку, а на ее месте создать другое окно - проблем не будет, ибо при разрушении формы FromHandle вернет указатель на другое окно и удалит его.
Если delete CBtnEdit (у которого bAutoDestroy == TRUE) - мы очень красиво разрушаем кучу, как раз методом двойного удаления объекта.
Если DestroyWindow текст или кнопку, то сам объект CWnd остается с нулевым хендлом, FromHandle его не найдет никогда - это memory leak.
Если DestroyWindow CBtnEdit - это одновременно и уничтожение CWnd - все ок.

Здесь есть вопрос, который я сам могу задать, себе же в основном.
Каким образом, при проходе по списку CtrlID, 1С определяет метод, которым надо уничтожать объекты?
Ну, потом разберемся, наверное, для полноты картины.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Создание элемента на форме
Ответ #37 - 21. Февраля 2008 :: 21:05
Печать  
kms писал(а) 21. Февраля 2008 :: 20:34:
Ну, схема комбинируется из описаний, данных разными авторами в предыдущих постах Улыбка

ИМХО, не совсем правильно она у тебя комбинируется Улыбка

kms писал(а) 21. Февраля 2008 :: 20:34:
Короче, 1С действительно не хранит ссылок на CWnd.

Зуб даешь?

kms писал(а) 21. Февраля 2008 :: 20:34:
Но тем не менее у нее есть массив CGetField*, а заодно и массив CGetCtrl*.
Впрочем, не суть, достаточно того, что она знает CtrlID этих окон.
При разрушении формы она проходит по списку CtrlID и как раз методом GetDescendantWindow/FromHandle получает CWnd*.

Это предположение или факт? Можешь сказать конкретную dll и адрес кода, который делает вышеописанное? Есть сомнения по этому поводу.

kms писал(а) 21. Февраля 2008 :: 20:34:
FromHandle может, конечно, возвращать CTempWnd, но как правило не возвращает, ибо существуют перманентные объекты, а у них приоритет.
Ну, дальше уничтожение объектов - дело техники.

Не очевидно.

kms писал(а) 21. Февраля 2008 :: 20:34:
В итоге получается такая картина:
Если delete текст или кнопку, а на ее месте создать другое окно - проблем не будет, ибо при разрушении формы FromHandle вернет указатель на другое окно и удалит его.

Не подтверждается. Перечитай эту тему внимательней. Мой объект CWnd 1С не удаляет. В частности, указатель на него можно удерживать в глобальном модуле - и спокойно обращаться к методам моего объекта. Удаление объекта происходит именно тогда, когда Я этого хочу.

kms писал(а) 21. Февраля 2008 :: 20:34:
Если delete CBtnEdit (у которого bAutoDestroy == TRUE) - мы очень красиво разрушаем кучу, как раз методом двойного удаления объекта.

Есть мнение, что все нетривиальные CWnd 1С используют механизм автоудаления. Ибо зачем плодить сущности сверх необходимого? Пусть самоудаляются после WM_DESTROY и все. Тогда циклы по CWnd * в деструкторе не нужны вообще.

kms писал(а) 21. Февраля 2008 :: 20:34:
Если DestroyWindow текст или кнопку, то сам объект CWnd остается с нулевым хендлом, FromHandle его не найдет никогда - это memory leak.

Если это временный объект, то он удалится MFC автоматически. Если это объект 1С, то зависит от объекта. Мне кажется, что в случае кнопок и надписей будут использоваться временные объекты MFC. Ибо для 1С не ни малейшего смысла создавать собственные объекты - логика надписи и кнопки тривиальна, тут нет необходимости навешивать дополнительный функционал. В этом случае при вызове delete мы уничтожим временный объект MFC, который потом повторно удалиться - со всеми вытекающими.

kms писал(а) 21. Февраля 2008 :: 20:34:
Если DestroyWindow CBtnEdit - это одновременно и уничтожение CWnd - все ок.

Здесь есть вопрос, который я сам могу задать, себе же в основном.
Каким образом, при проходе по списку CtrlID, 1С определяет метод, которым надо уничтожать объекты?
Ну, потом разберемся, наверное, для полноты картины.

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

В любом случае DestroyWindow - наиболее корректный способ удаления окна. В лучшем случае все будет работать ПОЛНОСТЬЮ корректно. В худшем случае возможен лик (в чем я сомневаюсь), но лучше сделать лик, чем разрушить кучу.
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Создание элемента на форме
Ответ #38 - 21. Февраля 2008 :: 22:05
Печать  
Uzhast писал(а) 21. Февраля 2008 :: 21:05:
ИМХО, не совсем правильно она у тебя комбинируется Улыбка

Оу, определенно, ты делаешь успехи по части дипломатии. Подмигивание

Цитата:
kms писал(а) 21. Февраля 2008 :: 20:34:
Короче, 1С действительно не хранит ссылок на CWnd.

Зуб даешь?

Фиг че. Но ссылок не хранит.

Цитата:
Это предположение или факт? Можешь сказать конкретную dll и адрес кода, который делает вышеописанное? Есть сомнения по этому поводу.

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

Цитата:
Есть мнение, что все нетривиальные CWnd 1С используют механизм автоудаления. Ибо зачем плодить сущности сверх необходимого? Пусть самоудаляются после WM_DESTROY и все. Тогда циклы по CWnd * в деструкторе не нужны вообще.

Точно, так и есть на самом деле.

Цитата:
Если это временный объект, то он удалится MFC автоматически.

Про временные можешь забыть, не видел ни одного.

Цитата:
Мне кажется, что в случае кнопок и надписей будут использоваться временные объекты MFC. Ибо для 1С не ни малейшего смысла создавать собственные объекты - логика надписи и кнопки тривиальна, тут нет необходимости навешивать дополнительный функционал. В этом случае при вызове delete мы уничтожим временный объект MFC, который потом повторно удалиться - со всеми вытекающими.

Не, логика есть, но не подтверждается.

Итак, резюмируя:
Цитата:
Считаю, (пока не доказано обратное), что:
- либо указатели на некоторые объекты 1С все же хранит

НЕТ для статика, кнопки, CBtnEdit

Цитата:
- либо нетривиальные объекты 1С самоуничтожаются

ДА

Цитата:
- либо комбинация двух вышеуказанных методов.

ХЗ, пока не встречалось

Цитата:
В любом случае DestroyWindow - наиболее корректный способ удаления окна. В лучшем случае все будет работать ПОЛНОСТЬЮ корректно. В худшем случае возможен лик (в чем я сомневаюсь), но лучше сделать лик, чем разрушить кучу.

Б"""", если ты такой умный, че ты это в первом посте ВСЮ механику не рассказал? Смех
  

De quelle planète es-tu?
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Создание элемента на форме
Ответ #39 - 21. Февраля 2008 :: 22:10
Печать  
Uzhast

А терь вопрос знатокам:
Почему для CBtnEdit* delete разрушает HEAP, а для CDrawStatic / CPictureButton7 - нет?

Помучайся немного. Очень довольный
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Создание элемента на форме
Ответ #40 - 21. Февраля 2008 :: 22:17
Печать  
kms писал(а) 21. Февраля 2008 :: 22:05:
Оу, определенно, ты делаешь успехи по части дипломатии. Подмигивание

Стараюсь...

kms писал(а) 21. Февраля 2008 :: 22:05:
Фиг че. Но ссылок не хранит.

Какие гарантии? Улыбка Думаешь, зря я про зуб антиресуюсь? Подмигивание

kms писал(а) 21. Февраля 2008 :: 22:05:
Блин, ну ты дотошный. Это хорошо.
Я тебе сказку рассказал, а ты вот в сказки не веришь.
Короче, нет там такого, это я так ненужные контролы прибивал, да так и осталось в голове Улыбка

Ага, говорил же, что схема сомнительная Улыбка
Но ведь тогда получается, что АБСОЛЮТНО все контролы 1С должны самоудаляться по DestroyWindow? Ведь если цикла удаления нет, объекты временными не являются, то другого варианта нет? Тем более в свете этих твоих слов:

kms писал(а) 21. Февраля 2008 :: 22:05:
Цитата:
Есть мнение, что все нетривиальные CWnd 1С используют механизм автоудаления. Ибо зачем плодить сущности сверх необходимого? Пусть самоудаляются после WM_DESTROY и все. Тогда циклы по CWnd * в деструкторе не нужны вообще.

Точно, так и есть на самом деле.


kms писал(а) 21. Февраля 2008 :: 22:05:
Про временные можешь забыть, не видел ни одного.

А, может, они прячутся?  Смех

kms писал(а) 21. Февраля 2008 :: 22:05:
Цитата:
Мне кажется, что в случае кнопок и надписей будут использоваться временные объекты MFC. Ибо для 1С не ни малейшего смысла создавать собственные объекты - логика надписи и кнопки тривиальна, тут нет необходимости навешивать дополнительный функционал. В этом случае при вызове delete мы уничтожим временный объект MFC, который потом повторно удалиться - со всеми вытекающими.

Не, логика есть, но не подтверждается.

Понятно. Т.е. надписи и кнопки - объекты нетривиальные?

kms писал(а) 21. Февраля 2008 :: 22:05:
Цитата:
- либо нетривиальные объекты 1С самоуничтожаются

ДА

Так что, получается догадка насчет правильности DestroyWindow ты подтверждаешь?

kms писал(а) 21. Февраля 2008 :: 22:05:
Цитата:
В любом случае DestroyWindow - наиболее корректный способ удаления окна. В лучшем случае все будет работать ПОЛНОСТЬЮ корректно. В худшем случае возможен лик (в чем я сомневаюсь), но лучше сделать лик, чем разрушить кучу.

Б"""", если ты такой умный, че ты это в первом посте ВСЮ механику не рассказал? Смех

Б"""", а если ТЫ такой умный, че ты мне весь расклад еще после первого поста не рассказал?  Смех
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Создание элемента на форме
Ответ #41 - 21. Февраля 2008 :: 22:22
Печать  
kms писал(а) 21. Февраля 2008 :: 22:10:
Uzhast

А терь вопрос знатокам:
Почему для CBtnEdit* delete разрушает HEAP, а для CDrawStatic / CPictureButton7 - нет?

Помучайся немного. Очень довольный

Думаешь, стоит? Улыбка DestroyWindow и вся недолга Улыбка

PS. Они что, в деструкторе ищут себя в таблице хендлов? И если не находят, не удаляются? Хотя, конечно, надо смотреть код... Улыбка
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Создание элемента на форме
Ответ #42 - 21. Февраля 2008 :: 23:00
Печать  
Да, текст и кнопка - нетривиальные.
И DestroyWindow() - самый корректный и безопасный вариант, никаких побочных эффектов типа ликов нет.

Гарантии - это вообще-то в отделе рекламаций, но навскидку есть основания полагать, что приличные гарантии, что общая схема именно такая.
Нетривиальные, самоликвидирующиеся в PostNcDestroy контролы, не требующие явного уничтожения в каком-либо цикле при закрытии формы.
Ну, можем посмотреть на остальные типы, когда время будет.

Uzhast писал(а) 21. Февраля 2008 :: 22:17:
Б"""", а если ТЫ такой умный, че ты мне весь расклад еще после первого поста не рассказал?  Смех

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

P.S.
Еще утром му""хался с этой темой.

В PurifyPlus знаешь как забавно выглядит "delete pWnd" для CBtnEdit*?
- error: read/write freed memory
- free location: delete pWnd
- error location: delete pWnd

Язык
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Kemet
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 46
Зарегистрирован: 03. Октября 2007
Re: Создание элемента на форме
Ответ #43 - 22. Февраля 2008 :: 03:15
Печать  
kms писал(а) 21. Февраля 2008 :: 23:00:
В PurifyPlus

А хде это чудо можно ...э... типа посмотреть? )
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Создание элемента на форме
Ответ #44 - 22. Февраля 2008 :: 04:46
Печать  
Kemet писал(а) 22. Февраля 2008 :: 03:15:
kms писал(а) 21. Февраля 2008 :: 23:00:
В PurifyPlus

А хде это чудо можно ...э... типа посмотреть? )

http://www-306.ibm.com/software/awdtools/purifyplus/
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1 2 [3] 4 
ОтправитьПечать