Я использую -fsanitize=leak и -fsanitize=address в моем проекте. Я думал, что утечка находит утечки памяти (не удаляет память), а адрес находит доступ к памяти wring. Но адрес также говорит о неразрушенной памяти. Итак, для каких целей -fsanitize=leak нужны?

1
dasfex 26 Апр 2020 в 23:37

2 ответа

Лучший ответ

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

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

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

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

3
Nicol Bolas 26 Апр 2020 в 20:53

Объяснение

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

Документация

Вы можете прочитать об этом на странице ga параметров инструментов программы.

-fsanitize=address

Включить AddressSanitizer, быстрый детектор ошибок памяти. Инструкции по доступу к памяти предназначены для обнаружения ошибок за пределами допустимого диапазона и использования после освобождения. Опция включает -fsanitize-address-use-after-scope. См. https://github.com/google/sanitizers/wiki/AddressSanitizer для получения дополнительной информации. подробности. На поведение во время выполнения можно влиять, используя переменную среды ASAN_OPTIONS. При значении help=1 доступные параметры отображаются при запуске инструментированной программы. См. https://github.com/google/sanitizers/wiki/AddressSanitizerFlags # run-time-flags для получения списка поддерживаемых опций. Эта опция не может быть объединена с -fsanitize=thread.

-fsanitize=leak

Включите LeakSanitizer, детектор утечки памяти. Эта опция имеет значение только для связывания исполняемых файлов, а исполняемый файл связан с библиотекой, которая переопределяет malloc и другие функции-распределители. См. https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer подробности. На поведение во время выполнения можно влиять, используя переменную среды LSAN_OPTIONS. Эта опция не может быть объединена с -fsanitize=thread.

-fsanitize-address-use-after-scope

Включите очистку локальных переменных, чтобы обнаружить ошибки использования после области. Опция устанавливает -fstack-reuse в none.

-fstack-reuse=reuse-level

Документацию можно найти на странице параметров кода поколения.

Эта опция контролирует повторное использование стекового пространства для объявленных пользователем локальных / авто переменных и сгенерированных компилятором временных переменных. reuse_level может быть «all», «named_vars» или «none». «All» разрешает повторное использование стека для всех локальных переменных и временных переменных, «named_vars» разрешает повторное использование только для определенных пользователем локальных переменных с именами, а «none» отключает повторное использование стека полностью. Значением по умолчанию является «все». Эта опция необходима, когда программа продлевает время жизни локальной переменной области действия или сгенерированного временного компилятора за пределы конечной точки, определенной языком. Когда время жизни переменной заканчивается, и если переменная живет в памяти, оптимизирующий компилятор может свободно использовать свое пространство стека с другими временными или локальными переменными с областями видимости, чей диапазон работы не перекрывается с ним. Устаревший код, расширяющий локальное время жизни, вероятно, сломается с оптимизацией повторного использования стека.

Например,

int *p;
{
  int local1;

  p = &local1;
  local1 = 10;
  ....
}

{
  int local2;
  local2 = 20;
  ....
}

if (*p == 10) // out of scope use of local1
{

}

Другой пример:

struct A {
  A(int k) : i(k), j(k) { }
  int i;
  int j;
};

A *ap;

void foo(const A& ar) {
  ap = &ar;
}

void bar() {
  foo(A(10)); // temp object's lifetime ends when foo returns

  {
     A a(20);
     ....
  }

  ap->i += 10; // ap references out of scope temp whose space
               // is reused with a. What is the value of ap->i?
}

Время жизни сгенерированного временного компилятора хорошо определено стандартом C ++. Когда время жизни временного элемента заканчивается, и если оно живет в памяти, оптимизирующий компилятор может свободно использовать свое пространство стека с другими временными или локальными переменными с областями видимости, чей диапазон действия не перекрывается с ним. Однако часть устаревшего кода зависит от поведения старых компиляторов, в которых пространство стека временных файлов не используется повторно, агрессивное повторное использование стека может привести к ошибкам во время выполнения. Эта опция используется для управления оптимизацией повторного использования временного стека.

3
user1032677 26 Апр 2020 в 22:30