Nano Hash - криптовалюты, майнинг, программирование

Почему free () обнуляет только 8 первых байтов?

У меня вопрос о поведении free ().

Используйте простой код, который использует malloc и strcpy a char *. Итак, все настроено на КУЧУ:

(gdb) x/100b 0x602010
0x602010:   66  111 110 106 111 117 114 32
0x602018:   116 111 117 116 32  108 101 32
0x602020:   109 111 110 100 101 0   0   0
0x602028:   0   0   0   0   0   0   0   0
0x602030:   0   0   0   0   0   0   0   0
0x602038:   33  0   0   0   0   0   0   0

Когда я освобождаю кусок с помощью free (), результат будет следующим:

(gdb) x/100b 0x602010
0x602010:   0   0   0   0   0   0   0   0
0x602018:   116 111 117 116 32  108 101 32
0x602020:   109 111 110 100 101 0   0   0
0x602028:   0   0   0   0   0   0   0   0
0x602030:   0   0   0   0   0   0   0   0
0x602038:   33  0   0   0   0   0   0   0

Простой код, подтверждающий, что:

int main ()
{
    const char * str = "Bonjour tout le monde";

    char *ptr = (char *) malloc (strlen(str) + 1);
    strcpy(ptr, str);

    printf("*ptr : %s\n\n", ptr);

    free(ptr);

    printf ("After free ptr = %p\n", ptr);
    printf ("Content ptr    : %s\n", ptr);
    printf ("Content ptr+8 : %s\n", ptr+8);

    return 0;
}

Вывод :

*ptr : Bonjour tout le monde

After free ptr = 0x13c7010
Content ptr    : 
Content ptr+8 : tout le monde

У кого-нибудь есть ответ?


  • В типичной реализации кучи функция free () добавляет блок обратно в список свободных блоков. Так что есть вероятность, что вы видите побочные эффекты этой операции с нулями, написанными, чтобы указать, что еще нет предыдущего и следующего указателей на другие свободные блоки. Посмотрите исходный код CRT. 17.02.2013
  • И много раз вы можете увидеть другие эффекты только что освобожденной памяти. Например, при использовании среды выполнения отладки большая часть блока памяти, вполне вероятно, будет заполнена некоторым значением, которое с большей вероятностью приведет к сбою вашей программы, если вы по ошибке ее используете - и это значение не будет равно нулю. По сути, как только вы освободите блок, он не ваш. Что с этим делает среда выполнения, зависит от среды выполнения. 17.02.2013

Ответы:


1

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

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

17.02.2013

2

Был бы лучший вопрос; как вы думаете, почему он должен делать что-то еще? Где вы нашли документацию, касающуюся обязательной реализации free? Его не существует, поэтому нет смысла задавать такой вопрос.

free просто нужно отметить эту память как освобожденную. Что происходит с этим блоком памяти после вызова free, не определено.


Кстати, это UB:

printf ("Content ptr    : %s\n", ptr);
printf ("Content ptr+8 : %s\n", ptr+8);
17.02.2013
  • Я никогда не думаю, что этот аргумент изменится после вызова free (), он будет таким же до и после free (), это просто информация для меня :). Спасибо за ответ, но что вы подразумеваете под определением реализации? 17.02.2013
  • Это означает, что каждый компилятор / среда выполнения могут делать все, что захотят. Он может обнулить освобожденную память (с потерей вычислительных циклов), а может и нет. Важно только то, что среда выполнения / O.S. теперь знает, что часть памяти снова свободна. 17.02.2013
  • @ j0llyJumper: Хорошо, я ушел с этой линии: printf ("After free ptr = %p\n", ptr); 17.02.2013
  • Небольшое исправление: то, что происходит с этим блоком памяти после вызова free, не определено в реализации. Фраза «реализация» имеет очень конкретное (и естественное) значение: реализация требуется для определения (как часть ее документации), что происходит. С другой стороны, попытка получить доступ к объекту после того, как его время жизни закончилось, имеет неопределенное поведение. 17.02.2013
  • @r: Я понимаю, что означает определение реализации. Как это не конкретная реализация? ничто в спецификации C не указывает, каким должно быть состояние этой памяти после вызова free, только то, что память снова помечается как свободная. Как память помечается как свободная и как она обрабатывается, зависит от реализации. Возможно, мы просто не понимаем друг друга. Кроме того, здесь нет UB, поскольку ptr никогда не разыменовывается после вызова free, но вы это знаете. 17.02.2013
  • @EdS .: Если что-то определено реализацией, вы можете ожидать, что документация компилятора / библиотеки точно скажет, как это обрабатывается. Страницы руководства обычно ничего не говорят о содержимом освобожденной памяти. И printf("... %s", ptr); это не UB? 17.02.2013
  • @aschepler: Да, мне очень жаль; Я пропустил %s. Это, безусловно, UB. Однако вы не обязательно найдете точное определение для всех аспектов спецификации, определяемых реализацией. Это просто означает, что реализация зависит от того, как с этим обращаться. Нет предписания, чтобы реализация указывала это вам (нам). Возможно, мне следовало просто сказать, что это не определено. 17.02.2013
  • @EdS .: Обычно фраза «реализация» имеет то техническое значение, которое дано в стандартах C и C ++: стандарты определяют определенные поведения, определяемые реализацией, то есть стандарт требует, чтобы реализация указывала нам поведение. Запись в освобожденную память не входит в число этих вещей. 17.02.2013
  • @aschepler: Я никогда не слышал эту последнюю часть, у вас есть ссылка? Во всяком случае, как я уже сказал; Я должен был сказать, что это не определено стандартом. 17.02.2013
  • @EdS .: C99 3.4.1 поведение, определяемое реализацией - неопределенное поведение, при котором каждая реализация документирует, как сделан выбор, 3.4.3 неопределенное поведение - поведение при использовании непереносимой или ошибочной программной конструкции или ошибочных данных, для которых это Международный стандарт не налагает требований, 3.4.4 неопределенное поведение - поведение, когда этот международный стандарт предоставляет две или более возможности и не налагает никаких дополнительных требований, которое выбирается в любом случае. Состояние освобожденного блока памяти не определено; это не определено, ясно и просто. 17.02.2013
  • Новые материалы

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

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..