Я запускаю простую основную программу на C++, в которой есть утечка. Когда я создаю эту программу через конфигурацию отладки CMAKE и запускаю ее. Он правильно показывает мне утечку. Но когда я создаю эту программу с конфигурацией выпуска CMAKE и запускаю ее. Пишет, что в программе нет утечек.
**main.cpp**
#include <ios>
#include <iostream>
#include <fstream>
#include <string>
#include <chrono>
using namespace std;
using namespace std::chrono;
int main(int argc, char **argv) {
std::cout << "Hello, World!\n";
int *i = new int[10]; //leak generating code
int j = rand()%9;
std::cout<<"j = "<<j<<std::endl;
if (j<0||j>9) return 0;
*(i+j) = 77;
std::cout<<"i = "<<*(i+j)<<std::endl;
return 0;
}
**CMakeLists.txt**
cmake_minimum_required(VERSION 3.1)
project(leakTest)
set(CMAKE_BUILD_RPATH "$ORIGIN")
if (CMAKE_VERSION VERSION_LESS "3.1")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else ()
set (CMAKE_CXX_STANDARD 11)
endif ()
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
add_executable(usingLeakTest main/src/main.cpp)
Cmake 3.8.x и 3.9.x использовались и опробовались с C++11.
Может ли кто-нибудь объяснить или помочь, почему это должно происходить?
Я запускаю приведенный выше код и CMAKE через CLION (конфигурация как отладки, так и выпуска). Это дает мне правильную утечку памяти в коде с отладочной сборкой, но с выпускной сборкой утечек не обнаружено.
Я тоже попробовал cmake -DCMAKE_BUILD_TYPE=Debug/Release
, и у меня такое же поведение.
В CMakeLists.txt я также пытался установить конфигурации ASAN через
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer -g -fsanitize-recover=address")
но это тоже не помогло.
Я также пытался предоставить ASAN_OPTIONS и LSAN_OPTIONS через терминал и через интерфейс CLION. но он работает неправильно и ведет себя так же.
Оптимизирующий компилятор избавляется от new
и создает эквивалентный код без утечек памяти.
#include <cstdlib>
#include <iostream>
int main(int argc, char** argv) {
std::cout << "Hello, World!\n";
int j = rand() % 9;
std::cout << "j = " << j << std::endl;
if (j < 0 || j > 9)
return 0;
std::cout << "i = " << 77 << std::endl;
return 0;
}
Посмотрите сгенерированный ассемблер на https://godbolt.org/z/8vsTa9GWv, выходная часть - это просто std::cout << 77
:
mov rdi, rax
mov esi, 77
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
Большое спасибо (273 КБ) [stackoverflow.com/users/6752050/273k] Вики, которой вы поделились, — отличная статья. Большое спасибо за помощь.
Итак, 273K вы хотите сказать, что компилятор компилирует код по-разному при сборке с помощью отладки и при сборке с выпуском? Также не могли бы вы поделиться некоторыми справочными конфигурациями cmake для правильной интеграции ASAN с проектом.