New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Указатели неправильно блокируются, что ломает любой код с ними #1155
Comments
P.S. исправьте, пожалуйста, побыстрее - это ломает так же и |
Вы что, хотите сборщика мусора для указателей? Не получится. Указатели на управляемые участки кода не разблокируются до окончания программы. Это естественное и очевидно ограничение. Блокируйте указатель явно (как этo в C#). fixed в паскале нет. Но можно вызывать явно GCHandle.Alloc и GCHandle.Free |
почему? вы ведь определяете где начало блока с указателем, и только тогда делаете блокировку. так же определите конец блока с указателем и там сделайте
Более того, из за того что вы Не добавили Если так уж хотите спихнуть блокируку указателей на ручное действие пользователей - уберите блокировку которая сейчас, потому что она обнуляет ручную. То есть если я напишу так:
Эта программа всё равно сжирает 1 гиг оперативки и всё равно временами выдаёт По крайней мере, если убрать блокировку что сейчас - ничего не сломается, что ещё не сломано. |
Надо делать так:
И будет занимать 5 мб памяти.
|
Нет не быстрее, потому что, повторюсь, В БЛОКИРОВКЕ КОТОРАЯ СЕЙЧАС НЕ УКАЗАНО А то что предложили вы - это очень много лишний действий, точнее преобразование + вызов метода, что негативно повлияет на производительность. |
Я вам предложил единственно верный вариант, который будет работать прозрачно и быстро. И переместит быстрее, это проверено на опыте. Делайте, как я сказал. |
Ваш вариант использует вызов метода + 2 вызова IL оператора И всё равно, оригинальные указатели значит сломаны, они могут вызвать ошибки. Почему вы не хотите убрать блокировку, если она не постоянно работает? Если уже не хотите исправить (что не должно быть сложно). Чтоб хотя бы можно было реализовать действительно быстро. |
И, кстати, это не то что надо опытом и "Я сказал, делайте как я сказал" доказывать, предоставьте тесты, в которых без недоблокировки |
Ну вот, запиннил я взятие адреса и ваш код все равно не работает. Память не освобождается. Так что берите код, который я вам привел.
Потому что программа упадет через 2 секунды при первом же проходе сборщика мусора. |
Эта программа сжирает 1 гигабайт памяти и отказывается его отдавать на
System.GC.Collect
.Но, что важнее - эта программа иногда выдаёт
System.AccessViolationException
!Смотрим в декомпилированный вариант:
Значит проблемы 2:
GCHandle.Alloc((object) numArray)
- это мало. Правильно -GCHandle.Alloc((object) numArray, GCHandleType.Pinned)
, без этого будем получатьSystem.AccessViolationException
при сборке мусора.Как сказано на msdn - если не указать какой тип блокировки - выбирается обычная, которая лишь не позволяет сборщику мусора удалить его, но позволяет перемещать.
Блокировка не освобождается. Надо присваивать результат
GCHandle.Alloc
переменной, и вызывать для неёFree
в конце блока кода, в котором объявлен указатель. При чём, это обязательно делать вtry finally
.Если не освободить блокировку - получаем утечки памяти, отсюда тот не высвобождаемый гигабайт.
Если не ставить в
try finally
- тоже получаем утечки памяти. Но только если будет исключение до высвобождения блокировки.The text was updated successfully, but these errors were encountered: