Telegram Group & Telegram Channel
GC Hole: чем ref отличается от указателя

GC Hole — баг, ситуация, когда в программе образуется ссылка на объект, уже собранный или перемещённый сборщиком мусора. Часто встречается в коде, который решили "микрооптимизировать".

Я никогда не встречал подобного бага вне кода, найденного в интернетах. Предположу, что его допускают в первую очередь программисты, переходящие на C# с языков с ручным управлением памятью — там аналогичная проблема называется use-after-free. По сути, GC Hole — частный случай use-after-free, только освобождение памяти выполняется не вручную, а сборщиком мусора.

Причина бага — попытка работать со ссылками на managed объекты как с адресами в памяти (числами).
Пример: long address = (long)Unsafe.AsPointer(ref value);

Пока на объект ссылаются обычными ссылками, или через `ref` — GC отслеживает эти ссылки и не будет собирать объект как мусор. При дефрагментации (compaction) кучи GC переместит объекты на новые места в памяти и обновит отслеживаемые им ссылки.

void*, int*, IntPtr, long и подобные типы — просто числа, GC про них ничего не знает. В итоге, если между получением адреса и его использованием случится GC — программа может обратиться уже по некорректному адресу и прочитать/перезаписать данные из случайного места. Потенциально, GC Hole — уязвимость, security bug.

Проблема может долго оставаться незамеченной, например, просто везёт и GC не успевает сработать, или ссылка ведёт в Large Object Heap, который не дефрагментируется в нормальном режиме.

Как избежать GC Hole:
- не пытаться превращать managed ссылки в адреса-числа

- не делать оптимизаций, которые дают выигрыш по производительности в пределах погрешности: обычно нет смысла использовать указатели, чтобы убрать проверки на выход за границы массива и выиграть 0.01%

- если очень надо, например для интеропа, использовать пиннинг (запрет GC перемещать объект при дефрагментации), с помощью fixed или GCHandle.Alloc(obj, GCHandleType.Pinned). Долгоживущие массивы можно аллоцировать в Pinned Object Heap

- осторожно работать с ref. ref может указывать на элемент массива или поле объекта

- использовать методы, работающие с ref, которые позволяют обойтись без перехода к адресам-числам:
- Unsafe.IsAddressLessThan(ref a, ref b) вместо Unsafe.AsPointer(ref a) < Unsafe.AsPointer(ref b)
- Unsafe.Add/Subtract, Unsafe.ByteOffset и подобные вместо арифметики указателей.

@epeshkblog | Поддержать канал



tg-me.com/epeshkblog/155
Create:
Last Update:

GC Hole: чем ref отличается от указателя

GC Hole — баг, ситуация, когда в программе образуется ссылка на объект, уже собранный или перемещённый сборщиком мусора. Часто встречается в коде, который решили "микрооптимизировать".

Я никогда не встречал подобного бага вне кода, найденного в интернетах. Предположу, что его допускают в первую очередь программисты, переходящие на C# с языков с ручным управлением памятью — там аналогичная проблема называется use-after-free. По сути, GC Hole — частный случай use-after-free, только освобождение памяти выполняется не вручную, а сборщиком мусора.

Причина бага — попытка работать со ссылками на managed объекты как с адресами в памяти (числами).
Пример: long address = (long)Unsafe.AsPointer(ref value);

Пока на объект ссылаются обычными ссылками, или через `ref` — GC отслеживает эти ссылки и не будет собирать объект как мусор. При дефрагментации (compaction) кучи GC переместит объекты на новые места в памяти и обновит отслеживаемые им ссылки.

void*, int*, IntPtr, long и подобные типы — просто числа, GC про них ничего не знает. В итоге, если между получением адреса и его использованием случится GC — программа может обратиться уже по некорректному адресу и прочитать/перезаписать данные из случайного места. Потенциально, GC Hole — уязвимость, security bug.

Проблема может долго оставаться незамеченной, например, просто везёт и GC не успевает сработать, или ссылка ведёт в Large Object Heap, который не дефрагментируется в нормальном режиме.

Как избежать GC Hole:
- не пытаться превращать managed ссылки в адреса-числа

- не делать оптимизаций, которые дают выигрыш по производительности в пределах погрешности: обычно нет смысла использовать указатели, чтобы убрать проверки на выход за границы массива и выиграть 0.01%

- если очень надо, например для интеропа, использовать пиннинг (запрет GC перемещать объект при дефрагментации), с помощью fixed или GCHandle.Alloc(obj, GCHandleType.Pinned). Долгоживущие массивы можно аллоцировать в Pinned Object Heap

- осторожно работать с ref. ref может указывать на элемент массива или поле объекта

- использовать методы, работающие с ref, которые позволяют обойтись без перехода к адресам-числам:
- Unsafe.IsAddressLessThan(ref a, ref b) вместо Unsafe.AsPointer(ref a) < Unsafe.AsPointer(ref b)
- Unsafe.Add/Subtract, Unsafe.ByteOffset и подобные вместо арифметики указателей.

@epeshkblog | Поддержать канал

BY .NET epeshk blog




Share with your friend now:
tg-me.com/epeshkblog/155

View MORE
Open in Telegram


telegram Telegram | DID YOU KNOW?

Date: |

What is Telegram Possible Future Strategies?

Cryptoassets enthusiasts use this application for their trade activities, and they may make donations for this cause.If somehow Telegram do run out of money to sustain themselves they will probably introduce some features that will not hinder the rudimentary principle of Telegram but provide users with enhanced and enriched experience. This could be similar to features where characters can be customized in a game which directly do not affect the in-game strategies but add to the experience.

Find Channels On Telegram?

Telegram is an aspiring new messaging app that’s taking the world by storm. The app is free, fast, and claims to be one of the safest messengers around. It allows people to connect easily, without any boundaries.You can use channels on Telegram, which are similar to Facebook pages. If you’re wondering how to find channels on Telegram, you’re in the right place. Keep reading and you’ll find out how. Also, you’ll learn more about channels, creating channels yourself, and the difference between private and public Telegram channels.

telegram from us


Telegram .NET epeshk blog
FROM USA