|
17 / 16 / 1
Регистрация: 25.01.2023
Сообщений: 468
|
||||||
.NET 4.x Почему сборщик не собирает объект файлового потока07.02.2024, 20:12. Показов 2718. Ответов 31
Метки нет (Все метки)
Здравствуйте. Имеется такой код
Вопрос, почему сборщик не всегда освобождает объект файлового потока? Предполагаю, что он не всегда успевает выполнить финализатор. P.S. имеется понимание, что в производственном коде потоки данных закрывают вручную. Разбор данного кода проводится исключительно в учебных целях.
0
|
||||||
| 07.02.2024, 20:12 | |
|
Ответы с готовыми решениями:
31
Почему событие eof() файлового потока наступает очень поздно? Какова вообще его логика? Почему объект типа std::vector не читается из потока? Состояние файлового потока |
|
62 / 187 / 31
Регистрация: 14.02.2013
Сообщений: 1,716
|
||
| 08.02.2024, 22:10 | ||
|
0
|
||
|
Модератор
|
|||||||
| 08.02.2024, 23:39 | |||||||
|
При оптимизации кода компилятор может решить, что раз нет дальше ссылок то сохранять объект не нужно. То есть по факту он может быть преобразован в такой:
0
|
|||||||
|
|
|||
| 08.02.2024, 23:52 | |||
|
0
|
|||
|
|
|||||||||||
| 09.02.2024, 00:19 | |||||||||||
|
На всякий -- с FileStream пример выше не применим по этой причине
В догонку х2: под "с FileStream пример выше не применим" подразумевал что поток будет закрываться, так как в деструкторе явный вызов Dispose, и фиг ты это как-то выпилишь (разве что переопределять сам Dispose, смотреть поток вызова и игнорить, что попахивает читерством). Важно другое -- потеряли ссылку на объект -> GC в неровен час объект приговорит. То что это открытый файл -- погоды не делает. Можно заменить мой код на это, и увидеть что кошка ровно также умирает, хотя файл никто явно не закрывал.
1
|
|||||||||||
|
Модератор
|
||
| 09.02.2024, 09:11 | ||
|
Но здесь возможна разница из-за фрейм платформ (Frame vs Core), из-за CLR на разных ОС. То есть, условно, код может работать на WibDesk без всяких багов, а на маках нет нет выкидывать исключения. По факту, то о чём написал INexteR, является багом. Так как никакая оптимизация не должна приводит к нестабильно работающему коду. Причины этой нестабильности поняты: какой-то из компиляторов не может уловить, что fs удерживает тот же файл что передаётся в метод Delete. Поэтому не удерживает ссылку на fs, что в исключительно редких случаях приводит к другому результату выполнения метода. В Core это уже пофикшено. Скорее всего не конкретно для потоков, а решение общее - все объекты сохраняемые в локальных переменных удерживаются до завершения работы метода независимо от оптимизации кода.Во Framework это не пофиксили, так как платформа официально уже не развивается. Добавлено через 2 минуты И как написал INexteR: Разбор данного кода проводится исключительно в учебных целях.То есть речь не о том, как правильно писать НА ПРАКТИКЕ. ТС это знает. А просто демонстрация и обсуждение одного из багов, который на практике может встретиться в исключительно редких случаях.
0
|
||
|
|
|
| 09.02.2024, 09:24 | |
|
Элд Хасп,
всё же мне кажется что если в стеке если переменная, и на этом уровне есть вызов GC -- магии не случится. Разве что компилятор решит влепить fs = null перед вызовом GC (вот этого не исключаю).Если же более обобщать: вызов GC в общем случае не приводить к моментальной финализации объекта. Ну т.е. это вот вообще ни разу не аналог delete из C++, а судя по примеру -- ожидалось нечто такое в поведении. Плюс ещё такой момент -- в финализацию объекта можно запихнуть столько кода, что убиваться он будет долго. К слову хороший вопрос -- если я влеплю Sleep -- GC будет ждать, и только потом приступит к остальным объектам?
0
|
|
|
Модератор
|
||
| 09.02.2024, 18:54 | ||
|
Другое дело, что на практике такая ситуация "один на миллион". Вполне возможно, что при оптимизации (двойной: C#->CIL->x86) на какой-то стадии решается, что ссылку на объект даже в стековую переменную сохранять не нужно. Получили в адресный регистр, вызвали метод объекта и никуда дальше адрес не сохраняют. Чтобы в этом разобраться надо очень глубоко опускаться - возможно до уровня машинных кодов. Это не нужно. Просто должно быть понимание, что во Framework есть такой редкий баг, поэтому не стоит так делать.
0
|
||
|
|
||||||||||
| 09.02.2024, 19:33 | ||||||||||
|
- либо у ТСа изначальный пример неправильный, так как он не высвобождает ресурс файла и дальше пытается его использовать в другом объекте. Так нельзя писать и точка. Сначала высвобождаем, и только потом используем по новой. - либо это псевдо-пример, чтобы понять когда высвобождается ресурс, и тогда ссылаясь на саму документацию
1
|
||||||||||
|
17 / 16 / 1
Регистрация: 25.01.2023
Сообщений: 468
|
|
| 10.02.2024, 14:57 [ТС] | |
|
Wolfdp, Приветствую, данный код служит не более чем примером для проверки на предмет того, как работает сборщик. Я сначала считал, что вызов метода Collect синхронный и что в таком случае сборщик гарантированно соберет неиспользуемый далее поток данных, вследствие чего всегда будет выводиться строка success. Но потом понял, что этот вызов асинхронный и что вызов метода Finalize не детерминирован. Его выполняет отдельный высокоприоритетный поток и он далеко не всегда успевает выполниться до конца, отпустив файл, и поэтому чаще выводится IOException. Но если сразу после вызова Collect вызвать GC.WaitForPendingFinalizers или Thread.Sleep(скажем, 1000), то всегда будет выводиться success.
0
|
|
|
|
|||||||
| 10.02.2024, 16:28 | |||||||
- вызываем GC - он отрабатывает 100500 объектов, финализирует их и всё такое - программа всё ещё занимает 100500 байт в ОЗУ. По идеи CLR может решить, что "мне эта память ещё дальше пригодиться, так что я её пока отдавать не буду".
1
|
|||||||
|
17 / 16 / 1
Регистрация: 25.01.2023
Сообщений: 468
|
|||||
| 10.02.2024, 18:39 [ТС] | |||||
|
0
|
|||||
|
|
|
| 10.02.2024, 19:46 | |
|
Детальней не подскажу.
Праздный вопрос -- вы с какой целью настолько подробно копаеет "во что комплилиться" и "когда вызывается GC и к чему это приводит"? Если к максимальной оптимизации кода прям на низком уровне -- ок, это скорее всего имеет смысл. Если чисто "чтобы знал, на практике пригодится"... ну, не уверен.
1
|
|
| 10.02.2024, 19:46 | |
|
Сборщик мусора не удаляет объект Передача файлового потока в функцию PyWin - чтение файлового потока
Переключение файлового потока ввода вывода Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами:
- ВидТО (СправочникСсылка. ВидыТО);
- ВидГСМ. . .
|
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала.
Ниже прикреплён. . .
|
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F
Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU.
Опрашиваются регистры. . .
|
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка:
Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
|
|
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо
Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
|
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман.
Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
|
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
|
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
|