Re: Garbage collection vs manual memory management
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.01.15 00:11
Оценка: +3 -1
Здравствуйте, johny5, Вы писали:

J>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.


Меня забавляет твой термин "С++ профессионал". Если ты проффесионал, то наличие конкретных свойств среду для тебя не должно быть ужасом.

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

Ну, а ты просто имеешь однобокий опыт. Расширить свой опыт и вопросы отпадут сами собой. Лично я сделал это более 10 лет назад. Полет нормальный.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Garbage collection vs manual memory management
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.01.15 00:16
Оценка:
Здравствуйте, johny5, Вы писали:

J>А если есть то не подчистится. А ссылки могут быть где угодно, в подписках на евенты, в кэше дот нета, нечаянно скаптурил this в какой то мелкой лямбде... И это лямбда потянет за собой ВСЁ.


У тебя синдром управления памятью. Для поиска "статической переменной в которую сложили весь мусор" есть довольно эффективные приложения. Случается это раз в 5 лет и ловится на раз.

Управлять нужно только неуправляемыми ресурсами. И в пример с твой кнопкой нужно тупо вызвать Dispse() который выгрузит все неуправляемые ресурсы. О памяти просто не надо думать. Она сама уйдет когда надо будет.

Работая со сложными структурами данных удержать граф зависимостей объектов в голве крайне не просто. GC позволяет просто не делать это. И это хорошо.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Garbage collection vs manual memory management
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.01.15 00:25
Оценка: +1
Здравствуйте, johny5, Вы писали:

J>Вопрос к вам ко всем, каков стиль программирования должен быть чтобы можно было бы писать в GC языках. Как добиваться модульности, ООП, когда не всё тянет всё, а модуль сам за себя и свои части отвечает. И, в частности, как вы делаете загрузку выгрузку данных модели, ведь от старых данных так просто не избавишься даже если ты скажешь Clear() всем контейнерам.


Это типичные плюсове предрассудки.

Память просто никто не выгружает. Сменил указатель на новое значение и все. Забыл про то что там было старое. Все выгружается автоматом. Нет ссылок, нет объекта.

Если у тебя будет случайно прикапываться старый указатель, то ты очень быстро заметишь потери памяти. Дальше остается только найти хороший профайлер памяти и найти это место.

Общие советы просы:
1. Не использовать статических переменных кроме как для организации неких сервисов доступных только для чтения.
2. Локализовывать работу с большими графами в отдельных функциях. Скажем у нас есть функция Parse() которая создает огромный граф объектов да еще и не один. Но по ее завершении ссылка на этот граф должна быть одна. И именно она возвращается из этой функции. Если не положить ее в статическую переменную, то рано или поздно она сдохнет.
3. Стараться локализовывать работу с неуправляемыми ресурсами в отдельных функциях. Прочел данные, переложил их в объекты и дальше работаешь с управляемыми объктоами.
4. Если специфика работы требует иметь некоторые догоживущие подключения (типа соеденения с БД), то использовать паттерн "Пул" выделяя холдеры ресурсов живщие только на время кратковременной обработки. Такой холдер засовывается в using и автоматически освобождается при выходе за пределы using-а. Он берет реальное подключение из пула и возвращает его обратно в своем Dispose().
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Garbage collection vs manual memory management
От: hi_octane Беларусь  
Дата: 09.01.15 01:23
Оценка:
J>Меня волнует другая тема: в C# / С++ главное отличие не в том что делаешь ты явно delete или среда подчистит его для тебя.
J>А главное тут в том что ты можешь сделать delete когда тебе угодно, а в C# нет.

Ну допустим смог ты delete и на две строчки ниже по этому же указателю обратился. Привет продакшн — лучший bounds checker!

И у C++ и у C# одна и та же проблема — ты можешь сделать какие-то действия (delete в C++, pointer = null в C#) и надеяться что произойдёт то что ты ожидаешь. Но трезво взгляни на вещи — ни в том ни в другом языке ты не знаешь что реально произойдёт, и в каком состоянии программа окажется после твоего delete.

Нужен механизм который бы гарантировал что после delete состояние программы полностью определено и синтаксис для описания того, что именно считать состоянием и как его определить. Как только такое чудо света кто-то придумает, так сразу и GC будет не нужен, и, внезапно, delete тоже будет не нужен. Ведь из описания такого контракта компилятору будет ясно что уже можно удалять, а что ещё нет.
Re[2]: Garbage collection vs manual memory management
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 09.01.15 05:54
Оценка: +1
Здравствуйте, hi_octane, Вы писали:

_>Нужен механизм который бы гарантировал что после delete состояние программы полностью определено и синтаксис для описания того, что именно считать состоянием и как его определить. Как только такое чудо света кто-то придумает, так сразу и GC будет не нужен, и, внезапно, delete тоже будет не нужен. Ведь из описания такого контракта компилятору будет ясно что уже можно удалять, а что ещё нет.


ATS же. Там все это было еще сто лет назад. Но на практике шибко сложно в использовании, дальше полутора академиков не пошло.
Re: Garbage collection vs manual memory management
От: andyag  
Дата: 09.01.15 06:57
Оценка: 4 (1)
Здравствуйте, johny5, Вы писали:

J>Общались с Джавистом пересевшим на С++. Мол висящие указатели, явная чистка памяти, и т.д. Всё это плохо и известно. Он предлагает универсальное решение — shared_ptr на всё. Я задал контрольный вопрос: есть кнопка, к ней привязан звук из менеджера звуков. Мы решили перегрузить менеджер звуков. Нам для этого старый нужно удалить а в новом все звуки загрузить заново. И что я слышу от него, оказывается это нормально в данном случае что кнопка на UI не даст старому звуковому менеджеру умереть!! А если там нужно драйвер переиниализировать, старый обязательно должен выгрузить своё.


Достаточно просто ввести посредника между кнопкой и менеджером звуков:
1. Продолжительность жизни посредника должна быть как минимум такой же, как продолжительность жизни кнопки
2. Посредник должен знать о существовании менеджера звуков
3. "Внешняя логика", которая перезапускает менеджер звуков, должна передавать посреднику ссылку на новый объект менеджера
Вот пример:
class SoundManager {...} // эту штуку вы хотите убивать и делать новую

class SoundService : IListenToSoundManagerUpdates 
{
  private SoundManager _soundManager;

  public void OnSoundManagerHasChanged(SoundManager sm)
  {
    _soundManager = sm;
  }

  public void PlaySound()
  {
    _soundManager.PlaySound();
  }
}

winAmpButton.Click += {
  _soundService.PlaySound();
};

restartSoundManagerButton.Click += {
  var soundManager = new SoundManager("another sound library");
  _soundService.OnSoundManagerHasChanged(soundManager);
};

Я не вижу чем принципиально будет отличаться решение на C++. В мире C#/Java можно ещё IoC-контейнер под это дело прикрутить, и "виртуализировать" SoundManager: снаружи он останется как есть, но внутри него будет SoundService со всеми вытекающими.

J>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.


Нужно контролировать не "физическую" жизнь объектов, а "логическую" — они не всегда совпадают. Вы описали задачу именно с точки зрения логической части, но свели проблему — к физической. С точки зрения "логической" части C#/Java легко дадут фору C++ хотя бы засчёт IoC-контейнеров.

J>Вопрос к вам ко всем, каков стиль программирования должен быть чтобы можно было бы писать в GC языках. Как добиваться модульности, ООП, когда не всё тянет всё, а модуль сам за себя и свои части отвечает. И, в частности, как вы делаете загрузку выгрузку данных модели, ведь от старых данных так просто не избавишься даже если ты скажешь Clear() всем контейнерам.


Вы бы показали как вы это на C++ делаете, можно было бы более предметно сравнить.
Re[3]: Garbage collection vs manual memory management
От: enji  
Дата: 09.01.15 10:14
Оценка:
Здравствуйте, johny5, Вы писали:

J>А если есть то не подчистится. А ссылки могут быть где угодно, в подписках на евенты, в кэше дот нета, нечаянно скаптурил this в какой то мелкой лямбде... И это лямбда потянет за собой ВСЁ.

J>Я об этом и говорю что тут токо сиди и надейся что оно сработает, нет в языке средств прямого управления временем жизни объекта.

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

Собственно и там и там надо принимать специальные меры — каптурить прокси к примеру...
Re[2]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 09.01.15 11:01
Оценка:
Здравствуйте, andyag, Вы писали:

A>
A>class SoundManager {...} // эту штуку вы хотите убивать и делать новую

A>class SoundService : IListenToSoundManagerUpdates 
A>{
A>  private SoundManager _soundManager;

A>  public void OnSoundManagerHasChanged(SoundManager sm)
A>  {
A>    _soundManager = sm;
A>  }

A>  public void PlaySound()
A>  {
A>    _soundManager.PlaySound();
A>  }
A>}

A>winAmpButton.Click += {
A>  _soundService.PlaySound();
A>};

A>restartSoundManagerButton.Click += {
A>  var soundManager = new SoundManager("another sound library");
A>  _soundService.OnSoundManagerHasChanged(soundManager);
A>};
A>


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

Давайте тогда рассмотрим пример что я получил на практике, и решения коему пока не нашёл.

Я создал модель, привязал модель к View (UI, WPF). Пришло время модель убить и загрузить новую.

Скажем так, несколько дней спустя я уже изменил все подписки на UI на weak subscription (это было сложно). И пробежал через все лямбды которые я где либо когда либо написал и кому то отдал, чтобы они неявно не каптурили this.

Оно всё равно не выгружается, потому что иногда, структуры данных (которые косвенно ссылаются на модель) которые генерит моя модель для UI, остаются в кэше WPF. Честно говоря, я спрятал ту косвенность под weak_ptr, но всё равно что то где то иногда не срабатывает и я сдался.

Я просто подумал что я явно тут делаю что то не так: в первом же приложении на C# пришлось использовать SoSEx, WeakPtr и страшные макросоподобные обёртки вокруг подписки на эвенты. ЧЯДНТ?


Ещё посмотрите пожайлуста на пост про модульность (rant можно опустить)
http://rsdn.ru/forum/philosophy/5916342.1
Автор: johny5
Дата: 09.01.15


Интересно ваше мнение.
Re: Просто сначала надо читать, а потом писать...
От: 11molniev  
Дата: 09.01.15 12:02
Оценка: +3
Чувствуется, что вместо того, что бы хотя бы бегло пробежаться глазами по спецификации языка и среды (а она даже на русский переведена...) вы попытались разобраться нахрапом.

J>Меня волнует другая тема: в C# / С++ главное отличие не в том что делаешь ты явно delete или среда подчистит его для тебя.

Не-а, главное отличие C++ RAII и C# GC в том, что первый отрабатывает при выходе за пределы видимости, а второй когда захочет. Или вы пишите на C++ в стиле восьмидесятых?
J>А главное тут в том что ты можешь сделать delete когда тебе угодно, а в C# нет.
Ошибочка, не когда угодно, а когда данный объект больше не будет использоваться. В одном случае это определяет программист и может ошибиться и удалить объект к которому ещё будут обращения, во втором среда и может недолго подержать в памяти объект к которому уже не будет обращений. Вот и вся разница — ничё больше.

J>Общались с Джавистом пересевшим на С++. Мол висящие указатели, явная чистка памяти, и т.д. Всё это плохо и известно. Он предлагает универсальное решение — shared_ptr на всё. Я задал контрольный вопрос: есть кнопка, к ней привязан звук из менеджера звуков. Мы решили перегрузить менеджер звуков. Нам для этого старый нужно удалить а в новом все звуки загрузить заново. И что я слышу от него, оказывается это нормально в данном случае что кнопка на UI не даст старому звуковому менеджеру умереть!! А если там нужно драйвер переиниализировать, старый обязательно должен выгрузить своё.

Все зависит от архитектуры, а не от языка. Если хочется, чтоб и кнопку не трогать и менеджер перезапускать когда приспичит и ресурсы на старый не тратить — то слабосвязанная архитектура с обменом сообщениями. И я для данной задачи в упор не вижу разницы между C# GC / C++ RAII / C void*. Что там, что там надо решать задачу жизни ресурса и во всех случаях подходы одинаковы. Применительно к вашему возмущению в сильно связанной архитектуре: ок, старый менеджер мы выгрузили, пользователь нажал кнопочку и мы радостно поперли по невалидному указателю/хендлу — это очень профессионально .

J>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.

Я совсем не понимаю, что вы подразумеваете под временем жизни объектов. В GC не надо контролировать время жизни выделенной памяти ибо предполагается, что можно пожертвовать несколькими десятками процентов. Время жизни ресурсов (сокеты, файлы, соединения с БД, ...) надо контролировать всегда и везде, вне зависимости от наличия или отсутствия GC. И отсутствие такого контроля — весьма грубая ошибка.

J>Я сам С++ник и безуспешно пытался пересесть на С#. Я поимел реальных проблем с тем что я впринципе не имею никакого контроля над временем жизни объектов мной созданных. К примеру загрузил я файл в модель, отобразил модель на форму и всё, хочу удалить и загрузить новую модель, но я не могу потому что в языке просто нет таких средств. Всё что тут можно сделать это подчистить везде везде везде ссылки на эту форму, на модель и скрестить пальцы что скоро всё само удалится. И всё равно не срабатывает в 50% случаях.

Я программировал на С++ до изучения С# и никаких проблем с последним не испытал. Время работы с файлом контролируется, хотя бы через using (хм, никакого контроля говорите?). А модель изменяется простым приравниванием. Что там вы имеете в виду под не могу удалить и причем здесь язык не ясно. Ссылки надо подчистить не на форму, а на модель (в С++ вы удаляете объект на который у вас ещё есть ссылки?). Срабатывает в ста случаях корректного использования (десятки лет эксплуатации .Net/Java подтверждают это).

J>Вопрос к вам ко всем, каков стиль программирования должен быть чтобы можно было бы писать в GC языках. Как добиваться модульности, ООП, когда не всё тянет всё, а модуль сам за себя и свои части отвечает. И, в частности, как вы делаете загрузку выгрузку данных модели, ведь от старых данных так просто не избавишься даже если ты скажешь Clear() всем контейнерам.

ХЗ. Вся разница, в том, что в языках без GC надо следовать более строгим правилам кодирования, дабы ничего не потерять. А программы с GC жрут памяти больше чем им нужно. Впрочем последнее больше серверная Java, чем .Net.
Re[3]: Garbage collection vs manual memory management
От: AlexRK  
Дата: 09.01.15 12:17
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>ATS же. Там все это было еще сто лет назад. Но на практике шибко сложно в использовании, дальше полутора академиков не пошло.


Rust же.
Re[2]: Garbage collection vs manual memory management
От: 0BD11A0D  
Дата: 09.01.15 12:17
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, johny5, Вы писали:


J>>Я до сих пор в шоке. Это ужос для С++ профессионала, вдруг оказаться в языке где ты не можешь контролировать жизнь объектов вокруг тебя.


VD>Меня забавляет твой термин "С++ профессионал". Если ты проффесионал, то наличие конкретных свойств среду для тебя не должно быть ужасом.


Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»). Распространять ужостики про другие языки — характерная часть этой профессии, потому, что язык очень часто используется неоправдано, и если этого не делать — их поувольняют и заменят более дешевыми.
Re[3]: Garbage collection vs manual memory management
От: AlexRK  
Дата: 09.01.15 12:28
Оценка:
Здравствуйте, 0BD11A0D, Вы писали:

BDA>Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»).


Это не единственное, а только одно из двух значений слова "профессионал".
Re[4]: Garbage collection vs manual memory management
От: 0BD11A0D  
Дата: 09.01.15 12:39
Оценка:
Здравствуйте, AlexRK, Вы писали:

BDA>>Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»).

ARK>Это не единственное, а только одно из двух значений слова "профессионал".

Да, есть еще вторая (секретная) этимология — от слов «проффесор» (с двумя «ф») и «анал». Засекречена по политическим причинам.

  Скрытый текст
Смысла в этом постинге нет никакого, кроме как разбавить глупость желчью. С целью предотвращения дальнейшего падения концентрации (каждый пусть сам решает, чего) в эту подветку больше не пишу.
Re[5]: Garbage collection vs manual memory management
От: AlexRK  
Дата: 09.01.15 12:46
Оценка:
Здравствуйте, 0BD11A0D, Вы писали:

BDA>>>Забавляет, потому, что многие забывают, что «профессионал» производное от «профессия» (и пишется с одной «ф»).

ARK>>Это не единственное, а только одно из двух значений слова "профессионал".

BDA>Да, есть еще вторая (секретная) этимология — от слов «проффесор» (с двумя «ф») и «анал». Засекречена по политическим причинам.


Fail.

м. 1) Тот, кто сделал какое-л. занятие своей профессией (противоп.: любитель). 2) Хороший специалист, знаток своего дела.


BDA>Смысла в этом постинге нет никакого, кроме как разбавить глупость желчью. С целью предотвращения дальнейшего падения концентрации (каждый пусть сам решает, чего) в эту подветку больше не пишу.


Ах, нет, только не это.
Re[3]: Garbage collection vs manual memory management
От: Sinix  
Дата: 09.01.15 12:55
Оценка:
Здравствуйте, johny5, Вы писали:

J>Я создал модель, привязал модель к View (UI, WPF). Пришло время модель убить и загрузить новую.

Сценарий нереалистичный (на практике время жизни модели совпадает с временем жизни ui), но ок.

Общий случай: делаем событие ModelChanged или ModelDisposed (если модель будет убиваться ровно один раз). Обработчики события подчищают лишние ссылки, проблема решена.
Если код модулей кривой и может упасть на ровном месте, придётся вместо простого вызова события получать всех подписчиков и оборачивать вызов каждого в try-catch с последующим бросанием AggregateException после вызова всех подписчиков. Иначе от утечек вы так никуда и не денетесь.


Для вашего конкретного случая: достаточно свойства CurrentModel. Код обращается к модели через это свойство, при необходимости подменить модель — меняем только значение свойства. Ну и не забываем про PropertyChanged, чтобы биндинг работал.

J>Оно всё равно не выгружается, потому что иногда, структуры данных (которые косвенно ссылаются на модель) которые генерит моя модель для UI, остаются в кэше WPF. Честно говоря, я спрятал ту косвенность под weak_ptr, но всё равно что то где то иногда не срабатывает и я сдался.

Вообще-то в wpf нет кэша. И как раз в wpf эта проблема решается элементарно — биндингом

J>Я просто подумал что я явно тут делаю что то не так: в первом же приложении на C# пришлось использовать SoSEx, WeakPtr и страшные макросоподобные обёртки вокруг подписки на эвенты. ЧЯДНТ?

Пытаетесь писать на шарпе в c++-стиле.
Re[3]: Пара примеров
От: andyag  
Дата: 09.01.15 13:10
Оценка:
Здравствуйте, johny5, Вы писали:

J>Здравствуйте, Васильич, Вы писали:


J>

Модульность


J>Модуль 1 подключается к Модулю 2.

J>Идёт обмен данными.
J>Модуль 2 кем то явно убивается.
J>Модуль 1 пытается опять подключиться к модулю 2.
J>Обмен данных не инициируется.

А приведите пожалуйста пример из реальной жизни. Глядя на эту абстрактную иллюстрацию первый вопрос, который хочется задать — а почему, собственно, они общающтся напрямую, но при этом одного из них убивает кто-то ещё? Нужна какая-то однозначная стратегия владения ("логического владения"). Например, "модуль 1 использует модуль 2" — в этом случае модуль 1 отвечает за уместное разрушение. Или "модуль 2 использует модуль 1" — аналогично. Если оба варианта не очень похожи на правду, есть третий — "модуль 3 использует модули 1 и 2" ("...просто вы его ещё не выделили из существующего кода"). Если у вас реально "общаются 1 и 2", эта часть решения — хороший кандидат на ревью: потому что обычно это на самом деле либо 1 модуль, либо 3, но не 2 (http://en.wikipedia.org/wiki/Circular_dependency). Это не всегда антипаттерн, но _очень часто_.

J>В С++ эта модульность — спасительный круг в мире висящих указателей, определённый функционал просто не будет запущен если какое то условие на более высоком уровне не было выдержано. В данном случае какой то блок внутри Модуля 1 будет просто отключен и что какие ссылки и структуры он содержит и куда оно всё ссылается оно всё становится неважно. По сути это приводит к повышению требования к качеству ООП в С++.


Не очень понятно. Обычно отключение куска кода — это в простейшем случае if вокруг какого-то флажка. Этим флажком кто-то должен управлять. В вашей иллюстрации, скорее всего, тот самый компонент, который "кто-то, кто явно убивает модуль 2". Убийство объекта это не delete, и не вызов сборщика мусора. Это в первую очередь заявление "этот объект теперь неактуален".

J>В C# же, модуль 2 всегда должен знать где как и кому он отдался, и возможно на Finalize сам должен уметь себя подчищать, .. и по моему небольшому опыту
Автор: johny5
Дата: 16.01.14
некоторые из этих случаев достаточно нетривиальны.


Снова — ну _очень_ абстрактно. Любой хеловорлд в 10 строчек помог бы сделать разговор более предметным.

J>

Копирование по значению


J>Тут я пытался придумать как копирование по значению в С++, поможет в данной проблеме но не нашёлся что написать... т.к. копирование, в общем случае, вызовет копирование всех ссылок внутри.


И вот опять. Ну серьёзно, покажите немного кода
Re[3]: Garbage collection vs manual memory management
От: andyag  
Дата: 09.01.15 13:10
Оценка:
Здравствуйте, johny5, Вы писали:

J>Здравствуйте, andyag, Вы писали:


A>>
A>>class SoundManager {...} // эту штуку вы хотите убивать и делать новую
A>>


J>Хорошо, это интересно. Посредник и правда решает эту задачу, хотя посредник будет вынужден полностью реплицировать интерфейс спрятанного им SoundManager.


Если решать в лоб, то да. Но вообще в Java/C# легко делаются всевозможные прокси объекты. Одна из популярных практик — описать какой-то "желаемый" интерфейс, а потом отдельно описать, что половина его реализации должна браться из вот этого объекта, вторая — из вон того, а третью вообще пусть фреймворк сам придумает как сделать. Посмотрите например вот сюда:
1. UserRepositoryCustom реализуется в UserRepositoryImpl
2. CrudRepository<User, Long> реализуется библиотекой
3. Из всего этого получается единственный объект с интерфейсом UserRepository, который выглядит "как надо".

J>Давайте тогда рассмотрим пример что я получил на практике, и решения коему пока не нашёл.

J>Я создал модель, привязал модель к View (UI, WPF). Пришло время модель убить и загрузить новую.
J>Скажем так, несколько дней спустя я уже изменил все подписки на UI на weak subscription (это было сложно). И пробежал через все лямбды которые я где либо когда либо написал и кому то отдал, чтобы они неявно не каптурили this.
J>Оно всё равно не выгружается, потому что иногда, структуры данных (которые косвенно ссылаются на модель) которые генерит моя модель для UI, остаются в кэше WPF. Честно говоря, я спрятал ту косвенность под weak_ptr, но всё равно что то где то иногда не срабатывает и я сдался.
J>Я просто подумал что я явно тут делаю что то не так: в первом же приложении на C# пришлось использовать SoSEx, WeakPtr и страшные макросоподобные обёртки вокруг подписки на эвенты. ЧЯДНТ?

А сильно сложно такого поведения на коротком примере добиться? Я последний год периодически пописываю UI на WPF и (видимых?) проблем с утечками нет. У вас оно прямо реально течёт или просто не исчезает, когда вы этого ожидаете? В плане наличия проблем "вообще", единственное, что могу предположить — вы используете какую-то "идиому", которая плохо ложится на GC.

J>Ещё посмотрите пожайлуста на пост про модульность (rant можно опустить)

J>http://rsdn.ru/forum/philosophy/5916342.1
Автор: johny5
Дата: 09.01.15


J>Интересно ваше мнение.


Написал комментарий.
Re[2]: Просто сначала надо читать, а потом писать...
От: johny5 Новая Зеландия
Дата: 09.01.15 13:40
Оценка:
Здравствуйте, 11molniev, Вы писали:

1> Ссылки надо подчистить не на форму, а на модель (в С++ вы удаляете объект на который у вас ещё есть ссылки?). Срабатывает в ста случаях корректного использования (десятки лет эксплуатации .Net/Java подтверждают это).


Кстате напомнило, в С++ когда ты объекту явно говоришь "умри", он сам мог отписаться автоматом от всего на что его подписали, используя boost::signals::trackable. Одна строка и досвиданья.

Не нашёл подобного механизма в C#, кроме того я вабще не понял как можно там отписываться. Ввод прокси объекта и занулять там указатель, это единственный вариант сделать подобное в C#?
Re[4]: Garbage collection vs manual memory management
От: johny5 Новая Зеландия
Дата: 09.01.15 13:48
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, johny5, Вы писали:


J>>Я создал модель, привязал модель к View (UI, WPF). Пришло время модель убить и загрузить новую.

S>Сценарий нереалистичный (на практике время жизни модели совпадает с временем жизни ui), но ок.

А тогда как вы иначе делаете Load данных с диска, убиваете и пересоздаёте форму целиком?


S>Для вашего конкретного случая: достаточно свойства CurrentModel. Код обращается к модели через это свойство, при необходимости подменить модель — меняем только значение свойства. Ну и не забываем про PropertyChanged, чтобы биндинг работал.


Прокси — понятно.


S>Вообще-то в wpf нет кэша. И как раз в wpf эта проблема решается элементарно — биндингом

Да нет, он там есть
Автор: johny5
Дата: 31.01.14
. Как раз вот это ощущение полного контроля над памятью что мы приносим из С++ и приводит к проблемам и попыткам контролировать всё в C#. Похоже в последнем нужно смириться что ты не имеешь контроля и защищаешь свои данные интерфейсами и прокси прослойками, чтобы всегда можно было бы перекрыть кран в одном узком месте.

Биндинг помоему тоже создаёт жёсткую ссылку, но тут неуверен. Как чистить ссылки биндинга — ума не приложу.


J>>Я просто подумал что я явно тут делаю что то не так: в первом же приложении на C# пришлось использовать SoSEx, WeakPtr и страшные макросоподобные обёртки вокруг подписки на эвенты. ЧЯДНТ?

S>Пытаетесь писать на шарпе в c++-стиле.

Понять бы что есть С# стиль..
Re[3]: Просто сначала надо читать, а потом писать...
От: Jack128  
Дата: 09.01.15 13:50
Оценка:
Здравствуйте, johny5, Вы писали:

J>Здравствуйте, 11molniev, Вы писали:


J>Кстате напомнило, в С++ когда ты объекту явно говоришь "умри", он сам мог отписаться автоматом от всего на что его подписали, используя boost::signals::trackable. Одна строка и досвиданья.


https://www.google.ru/search?ie=UTF-8&amp;hl=ru&amp;q=c%23%20weak%20events&amp;gws_rd=ssl
Это?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.