LINUX.ORG.RU

Почему надо проверять malloc на NULL

 , ,


1

3

Вообще выделение памяти проверять.

А вот потому что:

#include <stdio.h>
int main()
{
  unsigned char *a = NULL;
  int b = 0;
  unsigned long n = (unsigned long)&b;
 
  printf("b = %d, n = %lu\n",b,n);
  a[n]=1;
  printf("b = %d\n",b);
  return 0;
}

Запуск

$ gcc nullptr.c -o nullptr
$ ./nullptr 
b = 0, n = 140731726099148
b = 1

Запускалось в 64-битном (x86_64) Linux. Как видно, никаких сегфолтов и прочих ошибок. Конечно, адрес в районе 127 Тб в примере далеко за пределами доступного почти на всех компьютерах, но нет никаких гарантий, что на какой-то системе с каким-то компилятором и настройками среды значение не окажется более доступным. Могут быть и другие архитектуры (32-битные например), если запускать от root'а, то в начало может быть разрешена запись и там иметься память процесса. Или ещё какие-то варианты.

shdown, monk, liksys, Xenius - я думаю вам понравится. Пример сочинился по ходу чтения обсуждения Вышло издание 2,92 книги «Программирование: введение в профессию» А. В. Столярова (комментарий)

★★★★★

Последнее исправление: anonymous_incognito (всего исправлений: 1)
Ответ на: комментарий от bugfixer

Просто расскажите в 2х словах что по вашему мнению при внутренних ошибках такого модуля должно происходить?

Вы сначала в одном слове докажите, что вся эта эпопея имеет какое-то отношение исключительно к malloc’у и на любых других критических ошибках, не позволяющих продолжить выполнение операций, можно сделать что-то очень умное и продолжить работу как ни в чём ни бывало.

r--r--r--
()
Ответ на: комментарий от r--r--r--

Тут еще важный вопрос: откуда у bugfixer-а уверенность что если если на цепочке сообщений (m1, m2, …, mN) он инициирует abort, то затем на повторении этой же цепочки после рестарта не произойдет тоже самое.

У меня такое бывало: из-за бага в коде обработки сообщения типа X вылетало исключение, это исключение грохало процесс, процесс рестартовал, получает пачку сообщений от клиента, а в новой пачке вновь оказывалось сообщение X, исключение сново вылетало и процесс снова падал. И так постоянно до тех пор, пока у клиента истекало время жизни для X и клиент переставал его повторять.

Еще была история, но связанная с другой ситуацией. В приложении было несколько активных объектов каждый из которых работал со своей пачкой внешних сервисов (т.е. конектился к ним и через долгоживущие соединения обенивался кучей информации). Каждый такой активный объект сохранял свое состояние в БД. Иногда связь с БД рвалась, у активного объекта переставали проходить обращения к БД. Самым простым решением мне тогда показалось инициировать рестарт всего приложения если у какого-то из активных объектов начинались проблемы с БД (т.к. сложно было переделать логику активного объекта, который мог бы какое-то время работать без коннекта в БД).

Мне казалось, ну падает и рестартует процесс иногда, ну и какие проблемы, ничего же не теряется.

Но там получилось так, что если коннект к базе терялся, то с большой долей вероятности коннект терялся вскоре после рестарта. А потом еще раз. И так несколько раз, пока связь с серваком БД не восстанавливалась полностью.

А проблема пришла с неожиданной стороны – из-за падения приложения терялись подключения к внешним сервисам. Потом восстанавливались, потом опять терялись. И такое поведение очень сильно не нравилось владельцам этих сервисов. Они воспринимали такое как нарушение правил работы с их службами. Для них это выглядело как «подключение» - «выполнение одной операции» - «отключение». Что категорически не приветствовалось.

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

Было некритично, но неприятно.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Тут еще важный вопрос: откуда у bugfixer-а уверенность что если если на цепочке сообщений (m1, m2, …, mN) он инициирует abort, то затем на повторении этой же цепочки после рестарта не произойдет тоже самое.

Его это в принципе устраивает:

Почему надо проверять malloc на NULL (комментарий)
Почему надо проверять malloc на NULL (комментарий)

r--r--r--
()
Последнее исправление: r--r--r-- (всего исправлений: 1)

единственная на весь тред ситуация, когда казалось-бы «malloc()==NULL» дозволяет откатить и продолжить, описана топик-стартером. Заметим, что не апологетами этих самых откатов.

процесс читает файл и строит что-то там в памяти. Например читает json и конструирует DOM. Ну и как вы тут корректно обработаете ошибку с malloc==NULL, да ещё и чтобы продолжить работу, «отрехнулась и пошла» ?

вы-ж на словах, собаку съели с мишн-критикал и проектируете с учётом сбоев/ошибок.

MKuznetsov ★★★★★
()
Ответ на: комментарий от r--r--r--

Его это в принципе устраивает

Я прекрасно понимаю о чем bugfixer говорит и во многом с ним согласен в ситуациях, когда у разработчика все окружение под контролем (но категорически не согласен с пассажем про «лапки»).

Однако, даже когда мы договорились, что нехватка памяти – это жесткий форс-мажор, при котором жизни нет от слова совсем, то abort при NULL из malloc-а будет нормально работать только при условиях, что нехватка памяти возникает не из-за нас самих.

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

Это вполне себе OK.

Но вот если NULL возникает из-за проблем в нашем же коде. Приходит какой-то запрос от клиента, у нас есть ошибка в коде его обработки, из-за ошибки начинаем жрать память. Выжранная память приводит к NULL, мы идем в рестарт. После рестарта вновь получаем этот же запрос. Опять рестарт. И т.д., пока патч не выкатят.

И плохо здесь то, что сервер может параллельно работать с разными клиентами. Рестарт сервера из-за одной ошибки будет сказываться на всех клиентах. Все будут видеть разрывы, всем нужно переподключаться, перепосылать запросы и т.д., и т.п.

Поэтому даже когда для нас в принципе нормально прервать работу из-за NULL из malloc-а, могут быть неприятные моменты и циклы рестартов.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Я прекрасно понимаю о чем bugfixer говорит

Не могу этим похвастаться. Большая часть постов - это толчея воды в ступе и уход от вопросов.

Пока что всё выглядит так, что единственным аргументом в пользу аварийного завершения программы является какая-то глубокая душевная травма, полученная в ходе 25 лет работы над каким-то "менеджером", где в API не заложена возможность обработать корректно ошибку.

abort при NULL из malloc-а будет нормально работать только при условиях, что нехватка памяти возникает не из-за нас самих.

Но вот если NULL возникает из-за проблем в нашем же коде.

Я, признаться, с точки зрения обработки результатов вызова malloc принципиальной разницы не вижу.

Она тут есть с организационной точки зрения: кто крайний из-за отказа в обслуживании - разработчик или эксплуатация?

Кроме того, есть ещё третий сценарий, мой любимый - когда отказ в обслуживании вызван входящими данными. Сделали мы некую логику, она успешно работает на 99,9% случаев, пока не приходит тот самый 0,1, где надо выделить вместо килобайта гигабайт.

В кровавом о таких сценариях как правило вообще не думают, пока не выстрелит.

Я бы сказал, что abortится на NULL от malloc’а можно, если разраб живёт в серверной, прикованный цепью к стойке, и готов по первому дампу кидаться править код.

r--r--r--
()
Ответ на: комментарий от r--r--r--

Я, признаться, с точки зрения обработки результатов вызова malloc принципиальной разницы не вижу.

С точки зрения результатов обработки нет.

Есть с точки зрения простоты разработки. Одно дело писать софт под конкретные требования, которые будут обеспечиваться в рамках специального заповедника. Тогда можно исходить из того, что будет адекватный расчет объемов и мощностей, программа будет работать в условиях достатка памяти, поэтому можно сэкономить на разработке тем, что NULL из malloc – это всегда abort, и откаты в коде можно не писать и не тестировать.

Другое дело писать тот же коробочный софт где ни о каких адекватных расчетах объемов речи нет.

Кроме того, есть ещё третий сценарий, мой любимый - когда отказ в обслуживании вызван входящими данными. Сделали мы некую логику, она успешно работает на 99,9% случаев, пока не приходит тот самый 0,1, где надо выделить вместо килобайта гигабайт.

Вот тут вы прям в корень зрите.

Я бы сказал, что abortится на NULL от malloc’а можно, если разраб живёт в серверной, прикованный цепью к стойке, и готов по первому дампу кидаться править код.

Не исключено, то у bugfixer-а так и есть ;)

eao197 ★★★★★
()
Ответ на: комментарий от MKuznetsov

Ну и как вы тут корректно обработаете ошибку с malloc==NULL, да ещё и чтобы продолжить работу, «отрехнулась и пошла» ?

Освободил частично построенный DOM и return ENOMEM. А если на COPY temp (data) FROM 'data.json' при большом data.json будет падать вся СУБД, это намного хуже.

monk ★★★★★
()
Ответ на: комментарий от r--r--r--

В кровавом о таких сценариях как правило вообще не думают, пока не выстрелит.

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

anonymous_incognito ★★★★★
() автор топика
Ответ на: комментарий от anonymous_incognito

банках

Это далеко не самый кровавый - всё ключевое ПО там от третьих сторон.

аэропортах

Там вообще на грани автоматики и тоже ПО от третьих сторон.

r--r--r--
()
Ответ на: комментарий от monk

Освободил частично построенный DOM и return ENOMEM. А если на COPY temp (data) FROM 'data.json' при большом data.json будет падать вся СУБД, это намного хуже.

Типичная «шутка» на испытаниях - data.json FIFO от бесконечного генератора. Хорошо если парсер не recusrive-descendand. И в стресс-тестах, во время «освобождаю недостроенный XXX Gb DOM на мильоны узов» прилетит сигнал от OOM киллера.

по хорошему до malloc()==NULL не доводят. Это-ж UB во все поля, не понятно кто сожрал память, сколько сожрал, осталось/нет. И вероятность что процесс прямо сейчас снаружи прибьют резко возрастает. То если уж такое случилось, то «падают».

В приведённом примере, чтобы не доводить до нехорошего - память считают, для мелочи свой аллокатор, malloc()`ом берут разумно большие блоками (пулами),

при выходе за собственный софт-лимит, отдают пулы. И в nginx и в apache.

и уходят в точку восстановления (до уровня изоляции ошибки). Теперь можно, ситуация recoverable, до критической ошибки недошли.

А чтобы до точки добираться,и не изобретать exception на Си, 'COPY temp (data) FROM 'data.json' скорее корутина/green-thread, тогда её проще отбрасывать. Или скрипт, байт-код управляемой машины, тоже вполне изолирует.

то есть чтобы сделать возможным восстановление и предупреждать ошибки, это та ещё песня, непростой код и усилия во всём проекте.

не готовы тратить существенное время/деньги ? тогда if (malloc()==NULL) abort()

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

во время «освобождаю недостроенный XXX Gb DOM на мильоны узов» прилетит сигнал от OOM киллера

kill -9 от идиота тоже может вообще любую секунду прилететь. Если нужна стабильная работа, OOM киллер выключают, а резервирование памяти при выдаче включают.

И там, где есть OOM киллер, он прибьёт программу намного раньше, чем malloc вернёт NULL.

не понятно кто сожрал память, сколько сожрал, осталось/нет

Почему не понятно? Понятно, что памяти на данный момент больше нет. Никакого UB в этой ситуации нет. Часто можно даже сообщить пользователю о нехватке и уйти в ожидание, пока появится. Примерно так: https://i.sstatic.net/PNRZN.png

В приведённом примере, чтобы не доводить до нехорошего - память считают, для мелочи свой аллокатор, malloc()`ом берут разумно большие блоками (пулами),

От ООМ киллера не спасает. Он же не при маллоке прибегает, а когда кто-то начал писать в последнюю свободную страницу. И даже убивает не этого кого-то, а кого попало. Поэтому даже если в твоей программе вообще нет malloc, она всё равно может быть внезапно убита.

А чтобы до точки добираться,и не изобретать exception на Си, ’COPY temp (data) FROM ‘data.json’ скорее корутина/green-thread, тогда её проще отбрасывать.

Так abort() прибьёт всё приложение, а не корутину.

не готовы тратить существенное время/деньги ? тогда if (malloc()==NULL) abort()

А почему не if (malloc()==NULL) return ENOMEM?

monk ★★★★★
()
Ответ на: комментарий от monk

Примерно так:

картинка-то как раз выдана в ситуации до malloc=NULL. Софт (не будем показывать пальцем чей) сумел спрогнозировать потребности, оценить возможности и остановился ДО критической ошибки с неполучением памяти. Ему даже хватило ресурсов окошко нарисовать :-)

MKuznetsov ★★★★★
()

Стесняюсь спросить, а Вам зачем эти ритуалы с тайпкастингом на поинтеры понадобились?

Alfirin
()
Ответ на: комментарий от eao197

программа будет работать в условиях достатка памяти, поэтому можно сэкономить на разработке тем, что NULL из malloc – это всегда abort, и откаты в коде можно не писать и не тестировать.

Именно так. Более того - я в принципе считаю что останавливающийся конвеер лучше чем тот что начинает отхаркивать в вас покорёженными заготовками.

Не исключено, то у bugfixer-а так и есть ;)

Масштаб катастрофы вы, вероятно, даже не представляете ;) Но я вас уверяю что при всей его саркастичности - от такой «цепи» товарищ тоже бы не отказался. В дальнейшие детали я бы предпочёл не углубляться.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

от такой «цепи» товарищ тоже бы не отказался

Товарищ уже давно отказался от идей сидеть на цепи - несколько насиделся.

я вас уверяю

Возьмите себе за правило не говорить за других. Будете создавать у окружающих обманчивое впечатление взрослого человека.

r--r--r--
()
Ответ на: комментарий от MKuznetsov

картинка-то как раз выдана в ситуации до malloc=NULL.

В момент. Он запросил достаточное количество памяти для отмены, получил NULL и спросил, хочет ли пользователь продолжить, несмотря на то, что точку отмены не удалось создать.

Ещё можно вспомнить браузеры, которые при нехватке памяти закрывают одну вкладку,

СУБД, которые пишут в журнал

UTC ERROR:  out of memory
UTC DETAIL:  Failed on request of size 125.
UTC CONTEXT:  automatic analyze of table "xxx.public.delayed_jobs"
TopMemoryContext: 68688 total in 10 blocks; 4560 free (4 chunks); 64128 used

и завершают запрос, а не всю СУБД.

Ему даже хватило ресурсов окошко нарисовать :-)

Окошко нарисовано заранее, а делание окошка видимым malloc не вызывает.

monk ★★★★★
()
Ответ на: комментарий от monk

Окошко нарисовано заранее,

Нет. Со стороны user32.dll и менеджера сессий / граф. подсистемы для модальных окон заранее аллоцированы ресурсы. Это позволяет вывести диалог, даже если процесс в предсмертном состоянии.

Само окошко не только не нарисовано, но даже не существует до ошибки.

r--r--r--
()
Ответ на: комментарий от monk

В момент. Он запросил достаточное количество памяти для отмены, получил NULL

сильно вряд-ли :-) когда дошло до того что «пора пополнить пул», посмотрел что есть, проверил собственные лимиты и выкинул окошко. Или вообще на этапе планирования - прикинул сколько надо, сколько могут дать и пожаловался.

MKuznetsov ★★★★★
()
Ответ на: комментарий от r--r--r--

Само окошко не только не нарисовано, но даже не существует до ошибки.

Уверен? Тут же нет динамических данных. Оно может быть заранее нарисовано (и часто так делают).

monk ★★★★★
()
Ответ на: комментарий от MKuznetsov

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

monk ★★★★★
()
Ответ на: комментарий от monk

Оно может быть заранее нарисовано

Ты точно понимаешь смысл слова "нарисован"? "Нарисован" - это когда буфер с пикселями в видеопамяти.

(и часто так делают).

Так никогда не делают.

r--r--r--
()
Ответ на: комментарий от r--r--r--

Так никогда не делают.

Почему? Я в своих графических почти всегда так делал. Типа

GtkWidget *error_dialog, *complete_dialog, ...;

int main()
{
   ...
   error_dialog = init_error_dialog();
   complete_dialog = init_complete_dialog();
   ...
   ...
   ...
   gtk_main();
}

int f()
{
   ...
   if (error) {
      set_error_message(error_dialog, ERR_MSG42);
      gtk_widget_show(error_dialog);
      return;
   }
   ...
}

Это же быстрее, чем каждый раз отрисовывать диалог заново.

monk ★★★★★
()
Ответ на: комментарий от monk

Ты по-прежнему либо не понимаешь смысла слов, либо действий кода, которые пишешь.

До вызова gtk_widget_show(error_dialog); в видеопамяти нет ни одного пикселя от твоего диалога.

Это же быстрее,

Вообще без разницы. Машинерия на создание окон обычно копеечная.

r--r--r--
()
Ответ на: комментарий от bugfixer

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

Так эта схема позволяет перевезти большее кол-во авиапассажиров. На мой взгляд, плюсы перевешивают минусы.

BruteForce ★★★★
()
Ответ на: комментарий от bugfixer

Безусловно отличаются. Как ожидаемостью, так и возможностью последующей recovery.

Я запускаю веб-сервер. Он хочет открыть ключ для TLS, с диска. Ключа нет. Почему мне не надо делать abort()?

BruteForce ★★★★
()
Ответ на: комментарий от MKuznetsov

«malloc()==NULL» дозволяет откатить и продолжить

Вот ещё держи:

Пользователю показывают картинки, много, часто, случайно-разных, пользователь видит от C до 10*C картинок, это то кол-во картинок, которое должно быть единомоментно в памяти (x из [C,10*C]). Всего картинок N штук, это самое N огромно. Я пред-кеширую M картинок, то есть стараюсь держать кол-во загруженных в память, но ещё не показанных пользователю картинок ≤M. Итого держу в памяти ≤x+M+U картинок, где U — те, которые уже показаны, но я ещё не успел выгрузить или считаю, что они будут снова показаны ближайшее время и держу их в кэше. ЭВМ пользователя я не контролирую, кол-во доступной памяти для моей программы может меняться.

И вот, загружаю я очередную картинку. выделяю чанк памяти под ~10 типичных картинок. Системный аллокатор возвращает NULL.

ПредлОжите abort()?

BruteForce ★★★★
()
Ответ на: комментарий от BruteForce

Если хочешь сделать непадучую программу, то malloc-ом вообще нельзя пользоваться. Точнее один раз при старте, заховав памяти, сколько считаешь нужным, например, 1/3 ram и далее инициализировать её и работать только в пределах выделенного, сам распределяя под картинки сколько нужно. То есть со своим менеджментом памяти.

anonymous
()
Ответ на: комментарий от r--r--r--

До вызова gtk_widget_show(error_dialog); в видеопамяти нет ни одного пикселя от твоего диалога.

«Нарисовать» и «отобразить нарисованное» — это всё-таки разные процессы.

Машинерия на создание окон обычно копеечная.

По-всякому бывает. Если там какая-нибудь табличка с GtkList, может быть и долго.

monk ★★★★★
()
Ответ на: комментарий от anonymous

И запускать не на Линуксе. Или обеспечить, чтобы не было других процессов. Или хотя бы выключить ООМ киллера.

monk ★★★★★
()
Ответ на: комментарий от monk

«Нарисовать» и «отобразить нарисованное» — это всё-таки разные процессы.

Да, если используется двойная или тройная буферизация. Поэтому я использовал термин "видеопамять", а не "буфер экрана". В твоём сообщении нет возражения на мой пост.

r--r--r--
()
Последнее исправление: r--r--r-- (всего исправлений: 1)
Ответ на: комментарий от anonymous

Точнее один раз при старте, заховав памяти, сколько считаешь нужным, например, 1/3 ram и далее инициализировать её и работать только в пределах выделенного,

Пара таких программ и уже третью не запустишь. Отличное решение :) Для сервера под какую-то фиксированную задачу, даже наверное и здорово.

anonymous_incognito ★★★★★
() автор топика
Ответ на: комментарий от BruteForce

И вот, загружаю я очередную картинку. выделяю чанк памяти под ~10 типичных картинок. Системный аллокатор возвращает NULL.

ПредлОжите abort()?

Возможно это единственное место в вашей программе с более-менее понятной стратегией recovery (почистить кеш и попытаться снова). Если кеш картинок единственный «тяжелый» потребитель памяти - возможно даже имеет смысл пытаться его чистить когда NULL прилетает в алокациях не имеющих непосредственного отношения к этому кешу. А так да - прямиком в какую-то форму abort().

ПыСы. Что если вы просто медленно течёте?

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 2)
Ответ на: комментарий от bugfixer

Возможно это единственное место в вашей программе с более-менее понятной стратегией recovery (почистить кеш и попытаться снова).

Спасибо, что признаёте здесь возможность неупасть.

А так да - прямиком в какую-то форму abort().

Не признаёте(((

ПыСы. Что если вы просто медленно течёте?

Я не теку, потому что кэш это единственное место, где делается malloc это кеш, а free не вызывается вообще: «выгрузка» картинок это уменьшение счетчика хранимых картинок в кеш-чанке. Все кеш-чанки переиспользуются (когда счетчик хранимых картинок == 0, offset = 0 и пошли использовать этот чанк как ново-созданный).

Если течёт какая-то либа, которую я не контролирую, то обработка NULL всё равно сокращает отношение числа падений к числу запусков.

BruteForce ★★★★
()
Ответ на: комментарий от BruteForce

Я не теку, потому что кэш это единственное место, где делается malloc это кеш

Если это соответствует действительности, то очевидно что нужно делать. Однако терзают меня смутные сомнения…

Если течёт какая-то либа, которую я не контролирую, то обработка NULL всё равно сокращает отношение числа падений к числу запусков.

Вопрос скорее из философской плоскости. Встраивать излишний запас прочности тоже не всегда есть хорошо - у меня лично была ситуация когда один из инстансов модуля ковылял из последних сил, а узнал я об этом месяцы спустя когда этот инстанс окончательно сказал «ну не могу я больше». И в мире конечных ресурсов (ваших прежде всего, как программиста), я уверен, можно найти им лучшее применение чем войны с ветряными мельницами.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

ковылял из последних сил

… маскируя реальную и внешнюю по отношению к этому модулю проблему.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

Встраивать излишний запас прочности тоже не всегда есть хорошо

Да я согласен.

можно найти им лучшее применение чем войны с ветряными мельницами.

Однозначно

BruteForce ★★★★
()

Как думается, в предоставленном примере как минимум однажды (потенциально минимум дважды) сделано UB:

unsigned char *a = NULL;
[...]
a[n]=1;

и потенциально в
unsigned long n = (unsigned long)&b;

https://cstd.eisie.net/c23.html#6.3.2.3p6

safocl ★★
()
Ответ на: комментарий от anonymous_incognito

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

но ведь, как думается, потенциально нерабочий, поскольку любой выхлоп компилятора будет соответствовать стандарту C.

safocl ★★
()
Ответ на: комментарий от Xenius

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

когда у тебя UB в коде — может произойтить что угодно. Любое поведение программы будет соответствовать стандарту C (как и C++).

safocl ★★
()
Ответ на: комментарий от LightDiver

В раст сделать побитовую запись в произвольный адрес памяти невозможно без ансейф.

«[memory.bytes.intro] The most basic unit of memory in Rust is a byte.»
https://doc.rust-lang.org/reference/memory-model.html#r-memory.bytes.intro

что, как думается, подразумевает принципиальную невозможность побитовой записи в память вообще (как и в C, C++).

safocl ★★
()
Ответ на: комментарий от safocl

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

Я выше привел еще один такой вариант и могу придумать еще с пяток разных. И все это будет типа безопасно, но не то. Не прямая запись, как в оригинале.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 2)
Ответ на: комментарий от LightDiver

я говорил про «побитовую запись» таковая невозможна для велью-репрезентации. Минимально оперируемая сущность в памяти — это байт.

safocl ★★
()
Ответ на: комментарий от safocl

Я еще думал помню - исправлять не исправлять. Ай, думаю - похрен. И так все поймут о чем я.

LightDiver ★★★★★
()
Ответ на: комментарий от BruteForce

на С++ красиво получается, наверно, но я не експерт, и использую свою схему в стандартном контейнере массива покачто.

я создал модуль system - со статичными методами malloc/realloc/calloc/free/memcpy/memmove и считалку байт по типо сколько аллокаций сколько байт и сколько вызовов фри и счетчик байт на фри.

далее я сделал интрузиное устройство счетчика ссылок, это когда в массиве очищаем, ссылка выходя из области видимости удаляет обьект.

менеджер памяти можно дополнить стратегиями наследуясь от устройства интрузивного счетчика.

тогда получится через менеджер памяти мы вызываем бинды на вызов выделений памяти и очистки, в system при таком подходе можно закинуть и блочное управление памятью.

а массив в такой схеме владеет ссылкой с аллокатора(он же менеджер памяти) и аллокатор управляет памятью внутри контейнера.

получается на контейнерах если делать у нас есть контейнер окно (0, 10) и контейнер-кэш, определяем передачу данных через memmove/memcpy(trivialy) или просто копируем и вуаля у нас вроде управляемые эти штуки окно+кэш.

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от anonymous

защита заключается в том, что аллокатор можно создать явно в фрейме он будет жить дольше чем CustomArray, а обратная связь через ссылку позволяет оперировать адресом памяти, счетчика, тогда получается мы создаём такую конструкцию ради того, чтобы не писать так vector<MyClass*> temp;, мы выйдем за пределы и будет сегметейшн поидее, когда при обратной связи мы просто вызываем деструктор декрементируем счетчик, дальше там тонкости надо смотреть в дебагере удалять/не удалять, но накодить такую обратную связь ради времени жизни указателей, которые управляются через блок управления (поидее это интрузивный указатель) стоит, работает прикольно, я так отладился пока на кастомном массива, и на этом массиве кастомную хэш-мапу сделал с открытой адресацией, всё элегантно через аллокатор, а на С даже не знаю, у меня редактор текста на Аски строках, там 2/3 кода это просто управление буфером строк. разница в удобстве колосальная просто.

anonymous
()
Ответ на: комментарий от r--r--r--

ну по механике там под капотом делается map/unmap/reparent, если окно состоит из фреймворк елементов они предзагружены, но оформление как соломку надо подстелить понять, что это оповещение из готового ассета, и отобразить, куда интереснее когда он сделает цепочку настроек дойдя до репарент отрисовав и родителя и само приложение, получается на вейланде если я не ошибаюсь они переходят на систему владений почти тоже самое, но там прям читать надо в какой момент готовится шаред память на DE и/или WM, посмотрите если интересно пример tinyWM и там есть примеры простеньких WM, по простому там всё просто главное понять цепочку вызовов и когда стелить соломку оформлением, тот же старенький красивый мотиф работает ровно по тому же принципу.

anonymous
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария