Pull to refresh
68
nagg@Nagg

Разработчик

45
Subscribers
Send message

из примера выше:

public record class Cat(string Name);
public record class Dog(string Name);

public union Pet(Cat, Dog);

где тут нет объектов?

Вы не внимательно прочитали мой комментарий. Если вы записываете гуид и читаете в потоках, то максимум что вам грозит - это прочтение гуида где только часть записалась, а остальное - нули/мусор. Возможно это приведет к ошибкам в логике программы - но это уже на совести программиста. Несинхранизированная запись юниона, в котором вы делаете Unsafe.As над shared слотом в зависимости от тэга может привести к крашу рантайма. Фактически, это UB для джита/рантайма.

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

Никаким образом это не решает проблему. Представьте что у вас поле класса - юнион Pet pet. вы меняете значение этого поля с Cat на Dog. в каком порядке вы должны менять тэг и shared слот чтобы читающий это поле другой поток всё это увидел без потенциального краша рантайма?

Проблема ExplicitUnion в атомарности - вы должны и значение и тэг поменять атомарно, иначе это тайп-сефити баг потенциальный. А учитывая что больше чем 64 бита атомарно не поменять…

  • Думаю не надо объяснять что object и не-обджект в одном слоте вообще даже теоретически нельзя хранить в .NET

Имею право полагать, что до выхода Native AOT, возможности -p:PublishReadyToRun=true не было

Нет, не имеете. R2R был с самых первых версий .NET Core, до этого с нулевых (по-моему с .NET 2.0 или даже 1.1) был NGen - +/- тоже самое (чуть с другой философией, fragile). Какое-то время .NET Core даже поддерживал оба режиме - NGen и R2R.

"Появилось понятие R2R"

очень странная статья, понятно что это ИИ, но как-будто какой-то устаревший, из 2023 - смесь бесполезных фактов + откровенно неверных утверждений, аля

С выходом .NET 7.0 подход изменился. Появилось понятие R2R и Native AOT.

или

И все. Их только четыре. Больше не нужно.

наверное неверных утверждений еще больше, я вскольз глянул

развивается unsafe блок в статический анализатор как было с nullable reference types

Там скорее про то что большое кол-во public API начнут требовать unsafe{} контекст, т.к. они не безопасны. Остальное вокруг этого.

Мне было бы очень интересно посмотреть на примеры, которые стабильно эмитят tail call потестить

вот вам 2 примера https://godbolt.org/z/9ne5K5G16

Какую именно это меняет семантику и результат программы? наличие или нет StackOverflowException? это не семантика

В C# любая рекурсия (т.е. вызов функцией самой себя) требует O(n) памяти только для стека

Это не так, JIT компилятор где сможет, прекрасно расставляет тейл коллы сам (а в очень редких ситуациях может даже развернуть в цикл). tail. prefix который использует F# это больше как обязательное требование к рантайму, в духе "мне все равно как, сделай тут tail call, в случае если быстрый (имплицитный) тейл-колл нельзя вставить, джиту придется вставлять специальный хелпер колл от чего будет удар по перфу.

Я не думаю что есть хоть какие шансы на появление этого в синтаксисе C#, хз зачем вы его тут перечислили.

stackalloc или нет, это всё еще никак не связано с кэшем процессора или оперативной памятью, ортогональные вещи.

InlineArray даст защиту от выхода за границы (через исключение). в вашем случае это полный ансейф, сугубо на ваших плечах отвественность что вы правильно посчитали длины и оффсеты у Array

std::array<int, 10> -- это и есть const generics, под них надо изменять метадату, может когда и сделают, но для этого нужна везкая причина (в идеале, еще фичи которым нужны изменения)

var handlePtr = (IntPtr)Unsafe.AsPointer(ref handle);

Сразу видно, не читали статью ;-) вы тут делаете предположение что handle всегда на стеке или в нативной памяти, хотя ничего не помешает ему быть, например, полем класса или статическим полем и привет GC corruption баг (если это не ref struct конечно).

Т.е. вы используете неявный контракт вызова вашего метода, который никому не известен

Что конкретно непонятно? В целом, можно было реализовать через const generics, но неизвестно будут ли они когда-либо из-за сложности

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

Даже не знаю, что эти методы делают в Unsafe т.к. границы блоков памяти известны.

они являются unsafe потому что ничего вам не мешает ошибится с размером и это не вызовет никаких рантайм проверок. Вот пример:

byte[] a = new byte[10];
byte[] b = new byte[10];
Unsafe.InitBlockUnaligned(ref a[0], value: 42, byteCount: 40);

такой код даже отработает (и станет кандидатом в CVE)

Я лично не сильно фанат заметания unsafe под ковер. если у вас интероп слой, то и используйте в нем uv_getaddrinfo_t* и маршаллить ничего не надо, сразу в сигнатуре параметра объявить

1
23 ...

Information

Rating
7,223-rd
Registered
Activity