Воскресенье, 01 Декабря 2024, 21:15

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 2
  • 1
  • 2
  • »
Затирание данных перед освобождением
VuvkДата: Суббота, 15 Июля 2017, 08:31 | Сообщение # 1
заслуженный участник
Сейчас нет на сайте
Всем привет! Вопрос у меня не только по С/С++, но и вообще. Однако т.к. я задумался над этим, когда писал код на Си, то и разместил его здесь. Вопрос ламерский )
Итак, суть:
есть любая структура с несколькими полями -
Код

typedef struct
{
  float x, y, z;
  int anything;
} example_s;

В каком-то участке программы я её динамически создал:
Код

example_s* example = (example_s*)calloc(1, sizeof(example_s));

/* что-то с ней сделал и решил удалить */

memset(example, 0, sizeof(example_s));      /* вопрос */
free(example);
example = NULL;


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

Спасибо за внимание.


Сообщение отредактировал Vuvk - Вторник, 18 Июля 2017, 09:22
roma3fonДата: Суббота, 15 Июля 2017, 09:12 | Сообщение # 2
участник
Сейчас нет на сайте
Vuvk, может еще и ссылочные типы данных тоже затрирать?
В этом нет никакого смысла, только процессорное время потратишь.
П.С. От реверсеров затирание не поможет :)
VuvkДата: Суббота, 15 Июля 2017, 09:23 | Сообщение # 3
заслуженный участник
Сейчас нет на сайте
К счастью, в языке C ссылок нет))
За ответ спасибо.
puksusДата: Суббота, 15 Июля 2017, 14:33 | Сообщение # 4
Пчёлка Зоя
Сейчас нет на сайте
Vuvk, по сути, ссылка и указатель - одно и то же, то есть, ссылки "внутри" работают как указатели.

https://vk.com/beezoya
roma3fonДата: Суббота, 15 Июля 2017, 14:57 | Сообщение # 5
участник
Сейчас нет на сайте
puksus, lol crazy это вы красиво сказали!
А то что куча и стек статически не привязаны к адресному пространству и то что объект из кучи ссылается на методы, но хранит в себе поля, и то что на это все ссылается ключь из стека, так фигня. Просто указатель.


Сообщение отредактировал roma3fon - Суббота, 15 Июля 2017, 14:58
puksusДата: Суббота, 15 Июля 2017, 15:50 | Сообщение # 6
Пчёлка Зоя
Сейчас нет на сайте
roma3fon, я имел ввиду & ссылки, а не про типы данных вроде классов, хранящих указатели на виртуальные функции и которые да, действительно, мемсетом обнулять немножко глупо.
Но наверно это было не совсем в тему, потому что я сразу не понял, что вы имели ввиду под ссылочными типами, мой косячок.

Цитата roma3fon ()
А то что куча и стек статически не привязаны к адресному пространству

Не понял, поясните пожалуйста.


https://vk.com/beezoya
VuvkДата: Воскресенье, 16 Июля 2017, 08:56 | Сообщение # 7
заслуженный участник
Сейчас нет на сайте
Цитата
указатели на виртуальные функции и которые да, действительно, мемсетом обнулять немножко глупо.

С этим все ясно. Есть ли какие-то ситуации, когда не глупо - вот в чем вопрос. Просто разобраться хочу. %)

Добавлено (16 июля 2017, 08:56)
---------------------------------------------
Похоже в итоге натолкнулся на "неглупую" ситуацию, когда, по-видимому, не обойтись хотя бы без частичного затирания.
Опишу вкратце. Я пишу на Си, но всячески имитирую ООП-механизмы. Для определения к какому "классу" относится созданный объект (на основе структур) в них зашит в заголовок идентификатор (у каждого свой). Например, текстура:
Код

#define TXR_IDENT 0x5F525854   // 'T', 'X', 'R', '_' = 1599232084 = 0x5F525854

Проверка очевидна:
Код

bool ObjectIsTexture(void* object)
{
    if (object == NULL)
        return false;

    if (*((uint32*)object) == TXR_IDENT)
        return true;

    return false;
}

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

if (texture != NULL)
{
  if (ObjectIsTexture (texture))
  {
    /* использовать */
  }
  else
    texture = NULL;
}

Но если её не затереть (хотя бы идентификатор), то при обращении по адресу в мусоре может остаться верный идентификатор и всё, пиши пропало.
Такие соображения. Если у кого есть что конструктивного заметить, я только за.


Сообщение отредактировал Vuvk - Воскресенье, 16 Июля 2017, 09:06
OtinagiДата: Понедельник, 17 Июля 2017, 09:38 | Сообщение # 8
постоянный участник
Сейчас нет на сайте
У меня была проблема, правда это было на gcc на контроллерах. У меня было нечто вроде списка задач, и это было сделано как массив структур. В итоге, когда освобождалась последняя задача, изменялся размер массива, но всё равно можно было обратиться к уже несуществующему индексу и выполнить уже удалённую задачу, так как все данные там всё ещё в памяти были. И это постоянно возникало при работе с прерываниями, так как прерывание могло наступить в момент обработки и удаления события и в одном участке кода всё ещё оставался индекс последнего события. Так что, в некоторых случаях лучше затирать данные/часть_данных или хотя бы делать флаги, а лучше писать однозначный код - у MISRA-C много заметок по динамической работе с памятью. А использование всяческих ООП-механизмов не думаю, что хорошо для Си. Ещё и с NULL надо быть внимательным. В некоторых стандартах для систем с повышенной отказоустойчывастью советуют после освобождения памяти или создании указателя ручками ещё указателю NULL присваивать, иначе проверка на NULL может потом не сработать.

«Смерти меньше всего боятся те люди, чья жизнь имеет наибольшую ценность.»
Иммануил Кант
VuvkДата: Понедельник, 17 Июля 2017, 10:29 | Сообщение # 9
заслуженный участник
Сейчас нет на сайте
Цитата Otinagi ()
использование всяческих ООП-механизмов не думаю, что хорошо для Си

Без них разработка игр превращается в целую эпопею. Хотя и с ними не всё так гладко )

Цитата Otinagi ()
Ещё и с NULL надо быть внимательным. В некоторых стандартах для систем с повышенной отказоустойчывастью советуют после освобождения памяти или создании указателя ручками ещё указателю NULL присваивать, иначе проверка на NULL может потом не сработать.

Делаю это всегда. Без этого в моем проекте никак...

Цитата Otinagi ()
у MISRA-C много заметок по динамической работе с памятью

За наводку плюсик однозначно.

Добавлено (17 июля 2017, 10:29)
---------------------------------------------

Цитата Otinagi ()
У меня было нечто вроде списка задач, и это было сделано как массив структур

Думаю, что для списка надо было реализовать список, а не массив использовать. Это бы решило ряд проблем.
OtinagiДата: Вторник, 18 Июля 2017, 08:44 | Сообщение # 10
постоянный участник
Сейчас нет на сайте
Цитата Vuvk ()
Думаю, что для списка надо было реализовать список, а не массив использовать. Это бы решило ряд проблем.

Для PC, иногда, да; для контроллеров - определённо нет.

Цитата Vuvk ()
Без них разработка игр превращается в целую эпопею. Хотя и с ними не всё так гладко )

Согласен. Да не только игр. Сам для контроллеров нечто подобное ООПэшное реализовываю. Но падение производительности огромное, хоть и на порядок удобнее в итоге работать. Так что, очень сильно зависит от проекта и используемого оборудования. Хотя, если не изменяет память, даже Квейк 3 писался на Си, а не Си++. Так что, народ справлялся как-то и без ООП (:


«Смерти меньше всего боятся те люди, чья жизнь имеет наибольшую ценность.»
Иммануил Кант
VuvkДата: Вторник, 18 Июля 2017, 09:19 | Сообщение # 11
заслуженный участник
Сейчас нет на сайте
Цитата Otinagi ()
Хотя, если не изменяет память, даже Квейк 3 писался на Си, а не Си++. Так что, народ справлялся как-то и без ООП (:

Во всех движках idTech < 4 весьма себе объектно-ориентированный стиль. В рамках Си, конечно.

Добавлено (18 июля 2017, 09:19)
---------------------------------------------
Цитата Otinagi ()
Для PC, иногда, да; для контроллеров - определённо нет.

Подскажи, как специалист, почему? Или у тебя доступ не последовательный, а по номеру в массиве? Если так, то тут спору нет - оно и на ПК медленнее. Я в своем проекте остановился на списках, потому что мне нужно быстро то добавлять, то удалять элементы, а динамические массивы в этой ситуации - это грустно. Плюс мне нужно всегда проходить от первого элемента к последнему и обрабатывать их, нет необходимости дергать что-то в центре, например (либо оооочень редко).


Сообщение отредактировал Vuvk - Вторник, 18 Июля 2017, 09:20
OtinagiДата: Четверг, 20 Июля 2017, 09:35 | Сообщение # 12
постоянный участник
Сейчас нет на сайте
Цитата Vuvk ()
Во всех движках idTech < 4 весьма себе объектно-ориентированный стиль. В рамках Си, конечно.

Это да, правда я idTech 1 смотрел только. Там они извращались как могли, он весьма требователен получылся, и они там в итоге аккумулировали всё, что могли, чтобы побыстрее работало. Кстати, на мой взгляд, на этом движке (и ещё на движке Build [забавный факт, в этом движке нет ни одной вещественной переменной - это очень сильно повысило производительность и упростило математику]) можно много чему научыться, ибо на более поздних работах уже часто забивали на высокую производительность, ибо уповали на мощные компьютеры.

Цитата Vuvk ()
Подскажи, как специалист, почему?

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

Цитата Vuvk ()
Плюс мне нужно всегда проходить от первого элемента к последнему и обрабатывать их, нет необходимости дергать что-то в центре, например (либо оооочень редко).

К сожалению, у меня не всегда так. Часто идут обращения к конкретным элементам. И эти индексы так строго забиты, что бывали посреди массивов пустые места, когда событие удалилось, а массив не смещается. Кстати, массив тоже не динамический, а с заведомым запасом в своём размере, и, при добавлении нового события, цыклически ищет пустой индекс. Когда нужна производительность - приходится очень многим жертвовать и делать почти везде аккумуляторы. И "интеллектуально" выискивать простои в работе системы, когда можно будет всё упорядочыть, посоздавать новые аккумуляторы, поудалять уже точно не нужные и повыполнять прочее "сервисное" обслужывание программы. Но для PC программ это не очень актуально. Пользователи готовы и пару пару секунд подождать нажымая на кнопочки сайтов или вызывая менюшки с опцыями и сохранениями. А оперативную память можно условно назвать бесконечной и никогда не беспокоится об её исчерпании. Да и в играх современные гигагерцовые процессоры позволяют творить чудеса и не сильно заботиться о быстроте исполняемого кода.

Только не надо думать, что я против ООП и динамических структур данных (: Это всё замечательно и прекрасно и, наоборот, надо использовать, ибо очень удобно. Просто, попадались проекты, где их использование не давало нужную производительность. Это как рекурсия - если её запустить на контроллере, то сразу можно искать другую работу lol В то время, как обходы деревьев на PC, хоть и можно сделать без неё, но крайне неудобно. Так что, как любит говорить мой коллега, под каждую разработку надо выбирать подходящый стиль и язык программирования.



«Смерти меньше всего боятся те люди, чья жизнь имеет наибольшую ценность.»
Иммануил Кант


Сообщение отредактировал Otinagi - Четверг, 20 Июля 2017, 09:45
puksusДата: Четверг, 20 Июля 2017, 11:50 | Сообщение # 13
Пчёлка Зоя
Сейчас нет на сайте
Цитата Otinagi ()
и, при добавлении нового события, цыклически ищет пустой индекс.

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


https://vk.com/beezoya
SaiteiДата: Пятница, 21 Июля 2017, 11:12 | Сообщение # 14
старожил
Сейчас нет на сайте
Vuvk, на скорость выделения не влияют. НО после завершения работы твоей программы кто-нибудь может попробовать прочесть области оперативной памяти вместе с "не стёртыми" значениями
VuvkДата: Пятница, 21 Июля 2017, 12:57 | Сообщение # 15
заслуженный участник
Сейчас нет на сайте
Saitei, т.к. программа - самый обыкновенный игровой движок, то данное обстоятельство можно не учитывать ))

Сообщение отредактировал Vuvk - Пятница, 21 Июля 2017, 12:57
SaiteiДата: Пятница, 21 Июля 2017, 13:27 | Сообщение # 16
старожил
Сейчас нет на сайте
Vuvk, если хочешь увеличить скорость выделения и "освобождения" памяти под объекты - почитай что такое object pool

смысл один - заранее выделить память и раздавать определенные кусочки по требованию. "Освободить память" - означает пометить участок памяти как "свободен". И да, обычно освобождение памяти куда дороже выделения
giperionДата: Пятница, 28 Июля 2017, 11:33 | Сообщение # 17
участник
Сейчас нет на сайте
Saitei, я обратил внимание, что у меня malloc отрабатывать стал дольше, и вообще сцуко медленная функция. Это произошло когда я купил себе оперативы и работаю на компьютере где куча других программ.
Просто искать свободный блок в 8 больших модулях памяти, где уже забито другими приложениями - накладно даже для ОС. Раньше такого не было, это прерогатива современных компьютеров.
Освобождение памяти - операция даже проще выделения, но windows делает ещё дебажную проверку, поэтому это занимает долго.
Делать собственный memory pool - годная идея, главное не забывайте про выравнивание и фрагментирование и все будет хорошо.
Ну или на крайняк - выделяйте память без сериализации кучи. На винде ускоряет выделение значительно. Я почти уверен - у вас нету многопоточности :)


Skype: sergej_1965

Сообщение отредактировал giperion - Пятница, 28 Июля 2017, 11:34
VuvkДата: Пятница, 28 Июля 2017, 11:55 | Сообщение # 18
заслуженный участник
Сейчас нет на сайте
Цитата giperion ()
Я почти уверен - у вас нету многопоточности :)

На тему многопоточности тут провёл небольшое исследование. Хотел ускорить поиск элемента в двусвязном списке, запуская поиск с двух концов одновременно, пока один из потоков не наткнется на значение или на середину списка. Список липовый в 6000 элементов, и последовательно все опросил. Результат даже в зависимости от ОСи меня очень сильно удивил:

Ну и видимо в этой задаче оказалось совсем не резонно использовать потоки, т.к. на подготовку потоков и их запуск тратится много времени...
Цитаты из книги "Linux. Системное программирование":
Цитата
"Традиционно программы UNIX являются однопоточными, это связано с присущей UNIX простотой, быстрым созданием процессов и надежными механизмами межпроцессного взаимодействия. По всем этим причинам многопоточность не имеет в UNIX существенного значения."

Цитата
"На внутрисистемном уровне в ядре Linux реализуется уникальная разновидность потоков: фактически они представляют собой обычные процессы, которые по мере необходимости разделяют определенные ресурсы. В пользовательском пространстве Linux реализует потоки в соответствии со стандартом POSIX 1003.1c (также называемым Pthreads). Самый современный вариант реализации потоков в Linux именуется Native POSIX Threading Library (NPTL). Эта библиотека входит в состав glibc."


Сообщение отредактировал Vuvk - Пятница, 28 Июля 2017, 12:05
giperionДата: Воскресенье, 30 Июля 2017, 09:41 | Сообщение # 19
участник
Сейчас нет на сайте
Цитата Vuvk ()
Ну и видимо в этой задаче оказалось совсем не резонно использовать потоки, т.к. на подготовку потоков и их запуск тратится много времени...


Очень смешной тест.
А ты не пробовал использовать Thread Pool? У винды есть даже готовое встроенное API. Кинуть две задачи в тред пул, и ждать пока оба завершаться (ну или если пришел результат - сразу вернуть).
А запускать потоки динамически - все равно что в игре, при каждом тике заново грузить карту >_>


Skype: sergej_1965
VuvkДата: Воскресенье, 30 Июля 2017, 10:42 | Сообщение # 20
заслуженный участник
Сейчас нет на сайте
Цитата giperion ()
Очень смешной тест.

Возможно. Но тест проводился не для того, чтобы опорочить потоки, а для проверки нужны ли они для решения следующей задачи:
Дано: самописные двусвязные список и словарь на языке Си.
Задача: ускорить поиск значения по 1. номеру элемента и 2. по ключу
Решение: 1. определяем к какому концу ближе номер (к голове или к хвосту) и с той стороны и начинаем поиск
2. пустить поиск с двух концов, пока не будет обнаружен элемент или не достигнута середина. С потоками резона нет как показал тест выше.
  • Страница 1 из 2
  • 1
  • 2
  • »
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг