@re-shell/cli
Version:
Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja
2,159 lines (1,947 loc) • 70.3 kB
JavaScript
"use strict";
/**
* C++ Valgrind Memory Analysis Generator
* Generates Valgrind configuration and memory testing tools for C++ projects
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CppValgrindGenerator = void 0;
class CppValgrindGenerator {
static generate(config) {
const { projectName, enableMemcheck = true, enableHelgrind = true, enableCachegrind = true, enableCallgrind = false, enableMassif = true, enableDRD = false, suppressionFiles = [], customFlags = [] } = config;
return {
'valgrind/valgrind.cmake': this.generateValgrindCMake(projectName),
'valgrind/memcheck.supp': this.generateMemcheckSuppressions(),
'valgrind/helgrind.supp': this.generateHelgrindSuppressions(),
'scripts/run_valgrind.sh': this.generateValgrindScript(projectName, {
enableMemcheck,
enableHelgrind,
enableCachegrind,
enableCallgrind,
enableMassif,
enableDRD,
suppressionFiles,
customFlags
}),
'scripts/valgrind_analysis.py': this.generateValgrindAnalysis(),
'valgrind/README.md': this.generateValgrindReadme(projectName),
'.github/workflows/valgrind.yml': this.generateValgrindCI(projectName),
'valgrind/docker/Dockerfile.valgrind': this.generateValgrindDockerfile(),
'valgrind/configs/memcheck.conf': this.generateMemcheckConfig(),
'valgrind/configs/helgrind.conf': this.generateHelgrindConfig(),
'valgrind/configs/cachegrind.conf': this.generateCachegrindConfig(),
'valgrind/configs/massif.conf': this.generateMassifConfig(),
'scripts/memory_report.py': this.generateMemoryReport()
};
}
static generateValgrindCMake(projectName) {
return `# Valgrind Integration for ${projectName}
# Memory analysis and profiling tools
find_program(VALGRIND_EXECUTABLE valgrind)
if(VALGRIND_EXECUTABLE)
message(STATUS "Valgrind found: \${VALGRIND_EXECUTABLE}")
# Valgrind configuration
set(VALGRIND_COMMON_FLAGS
--tool=memcheck
--leak-check=full
--show-leak-kinds=all
--track-origins=yes
--verbose
--error-exitcode=1
--gen-suppressions=all
--suppressions=\${CMAKE_SOURCE_DIR}/valgrind/memcheck.supp
)
# Create valgrind targets for all executables
function(add_valgrind_test TARGET_NAME)
cmake_parse_arguments(
VALGRIND
"MEMCHECK;HELGRIND;CACHEGRIND;CALLGRIND;MASSIF;DRD"
"WORKING_DIRECTORY;TIMEOUT"
"ARGS;SUPPRESSIONS"
\${ARGN}
)
if(NOT VALGRIND_WORKING_DIRECTORY)
set(VALGRIND_WORKING_DIRECTORY \${CMAKE_CURRENT_BINARY_DIR})
endif()
if(NOT VALGRIND_TIMEOUT)
set(VALGRIND_TIMEOUT 300)
endif()
# Memcheck (default)
if(VALGRIND_MEMCHECK OR NOT (VALGRIND_HELGRIND OR VALGRIND_CACHEGRIND OR VALGRIND_CALLGRIND OR VALGRIND_MASSIF OR VALGRIND_DRD))
set(MEMCHECK_FLAGS
--tool=memcheck
--leak-check=full
--show-leak-kinds=all
--track-origins=yes
--verbose
--error-exitcode=1
--xml=yes
--xml-file=\${CMAKE_BINARY_DIR}/valgrind_\${TARGET_NAME}_memcheck.xml
--suppressions=\${CMAKE_SOURCE_DIR}/valgrind/memcheck.supp
)
foreach(SUPP_FILE \${VALGRIND_SUPPRESSIONS})
list(APPEND MEMCHECK_FLAGS --suppressions=\${SUPP_FILE})
endforeach()
add_test(
NAME valgrind_memcheck_\${TARGET_NAME}
COMMAND \${VALGRIND_EXECUTABLE} \${MEMCHECK_FLAGS} \$<TARGET_FILE:\${TARGET_NAME}> \${VALGRIND_ARGS}
WORKING_DIRECTORY \${VALGRIND_WORKING_DIRECTORY}
)
set_tests_properties(valgrind_memcheck_\${TARGET_NAME} PROPERTIES
TIMEOUT \${VALGRIND_TIMEOUT}
LABELS "Valgrind;Memcheck;Memory"
)
endif()
# Helgrind (thread error detection)
if(VALGRIND_HELGRIND)
set(HELGRIND_FLAGS
--tool=helgrind
--verbose
--error-exitcode=1
--xml=yes
--xml-file=\${CMAKE_BINARY_DIR}/valgrind_\${TARGET_NAME}_helgrind.xml
--suppressions=\${CMAKE_SOURCE_DIR}/valgrind/helgrind.supp
)
add_test(
NAME valgrind_helgrind_\${TARGET_NAME}
COMMAND \${VALGRIND_EXECUTABLE} \${HELGRIND_FLAGS} \$<TARGET_FILE:\${TARGET_NAME}> \${VALGRIND_ARGS}
WORKING_DIRECTORY \${VALGRIND_WORKING_DIRECTORY}
)
set_tests_properties(valgrind_helgrind_\${TARGET_NAME} PROPERTIES
TIMEOUT \${VALGRIND_TIMEOUT}
LABELS "Valgrind;Helgrind;Threading"
)
endif()
# Cachegrind (cache profiling)
if(VALGRIND_CACHEGRIND)
set(CACHEGRIND_FLAGS
--tool=cachegrind
--verbose
--cachegrind-out-file=\${CMAKE_BINARY_DIR}/cachegrind_\${TARGET_NAME}.out
)
add_test(
NAME valgrind_cachegrind_\${TARGET_NAME}
COMMAND \${VALGRIND_EXECUTABLE} \${CACHEGRIND_FLAGS} \$<TARGET_FILE:\${TARGET_NAME}> \${VALGRIND_ARGS}
WORKING_DIRECTORY \${VALGRIND_WORKING_DIRECTORY}
)
set_tests_properties(valgrind_cachegrind_\${TARGET_NAME} PROPERTIES
TIMEOUT \${VALGRIND_TIMEOUT}
LABELS "Valgrind;Cachegrind;Performance"
)
endif()
# Callgrind (call profiling)
if(VALGRIND_CALLGRIND)
set(CALLGRIND_FLAGS
--tool=callgrind
--verbose
--callgrind-out-file=\${CMAKE_BINARY_DIR}/callgrind_\${TARGET_NAME}.out
--dump-instr=yes
--collect-jumps=yes
)
add_test(
NAME valgrind_callgrind_\${TARGET_NAME}
COMMAND \${VALGRIND_EXECUTABLE} \${CALLGRIND_FLAGS} \$<TARGET_FILE:\${TARGET_NAME}> \${VALGRIND_ARGS}
WORKING_DIRECTORY \${VALGRIND_WORKING_DIRECTORY}
)
set_tests_properties(valgrind_callgrind_\${TARGET_NAME} PROPERTIES
TIMEOUT \${VALGRIND_TIMEOUT}
LABELS "Valgrind;Callgrind;Profiling"
)
endif()
# Massif (heap profiling)
if(VALGRIND_MASSIF)
set(MASSIF_FLAGS
--tool=massif
--verbose
--massif-out-file=\${CMAKE_BINARY_DIR}/massif_\${TARGET_NAME}.out
--heap=yes
--stacks=yes
--time-unit=ms
)
add_test(
NAME valgrind_massif_\${TARGET_NAME}
COMMAND \${VALGRIND_EXECUTABLE} \${MASSIF_FLAGS} \$<TARGET_FILE:\${TARGET_NAME}> \${VALGRIND_ARGS}
WORKING_DIRECTORY \${VALGRIND_WORKING_DIRECTORY}
)
set_tests_properties(valgrind_massif_\${TARGET_NAME} PROPERTIES
TIMEOUT \${VALGRIND_TIMEOUT}
LABELS "Valgrind;Massif;Heap"
)
endif()
# DRD (data race detection)
if(VALGRIND_DRD)
set(DRD_FLAGS
--tool=drd
--verbose
--error-exitcode=1
--xml=yes
--xml-file=\${CMAKE_BINARY_DIR}/valgrind_\${TARGET_NAME}_drd.xml
)
add_test(
NAME valgrind_drd_\${TARGET_NAME}
COMMAND \${VALGRIND_EXECUTABLE} \${DRD_FLAGS} \$<TARGET_FILE:\${TARGET_NAME}> \${VALGRIND_ARGS}
WORKING_DIRECTORY \${VALGRIND_WORKING_DIRECTORY}
)
set_tests_properties(valgrind_drd_\${TARGET_NAME} PROPERTIES
TIMEOUT \${VALGRIND_TIMEOUT}
LABELS "Valgrind;DRD;Threading"
)
endif()
endfunction()
# Custom targets for comprehensive analysis
add_custom_target(valgrind_all
COMMENT "Running all Valgrind tools"
)
add_custom_target(valgrind_memcheck
COMMENT "Running Valgrind Memcheck"
)
add_custom_target(valgrind_helgrind
COMMENT "Running Valgrind Helgrind"
)
add_custom_target(valgrind_cachegrind
COMMENT "Running Valgrind Cachegrind"
)
add_custom_target(valgrind_massif
COMMENT "Running Valgrind Massif"
)
# Function to automatically add valgrind tests for all executables
function(enable_valgrind_for_target TARGET_NAME)
add_valgrind_test(\${TARGET_NAME} MEMCHECK HELGRIND CACHEGRIND MASSIF)
endfunction()
else()
message(WARNING "Valgrind not found. Memory analysis tools will not be available.")
# Provide stub functions
function(add_valgrind_test TARGET_NAME)
# Do nothing
endfunction()
function(enable_valgrind_for_target TARGET_NAME)
# Do nothing
endfunction()
endif()
# Valgrind-specific compile flags
function(add_valgrind_flags TARGET_NAME)
target_compile_options(\${TARGET_NAME} PRIVATE
-g3 # Maximum debug information
-O0 # No optimization for accurate results
-fno-omit-frame-pointer # Keep frame pointers for stack traces
-fno-inline-functions # Disable inlining for clearer traces
)
target_compile_definitions(\${TARGET_NAME} PRIVATE
VALGRIND_BUILD=1
)
endfunction()
# Integration with existing project
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND VALGRIND_EXECUTABLE)
# Automatically enable valgrind for debug builds
set(ENABLE_VALGRIND_BY_DEFAULT ON)
else()
set(ENABLE_VALGRIND_BY_DEFAULT OFF)
endif()
option(ENABLE_VALGRIND "Enable Valgrind memory analysis" \${ENABLE_VALGRIND_BY_DEFAULT})`;
}
static generateMemcheckSuppressions() {
return `# Valgrind Memcheck Suppressions
# Common false positives and known issues
# Standard library suppressions
{
std_string_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:_ZNSs4_Rep9_S_createEmm*
fun:_ZNSs4_Rep8_M_cloneERK*
fun:_ZNSs7reserveEm
}
{
std_locale_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
obj:*libstdc++*
fun:_ZNSt6locale5facet*
}
# Thread-local storage suppressions
{
tls_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:calloc
fun:_dl_allocate_tls
fun:pthread_create@@GLIBC_*
}
# C++ global constructors/destructors
{
global_constructor_leak
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:__static_initialization_and_destruction_*
}
{
global_destructor_leak
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:__cxa_atexit
}
# OpenSSL suppressions
{
openssl_init_leak
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:CRYPTO_malloc
fun:*SSL_library_init*
}
# glibc suppressions
{
glibc_dl_init
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_dl_new_object
fun:_dl_map_object_from_fd
}
{
glibc_getpwuid
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:nss_parse_service_list
fun:__nss_database_lookup
}
# Boost suppressions
{
boost_thread_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:_ZN5boost6thread*
}
# JSON library suppressions (nlohmann/json)
{
json_allocator_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:_ZN8nlohmann*
}
# HTTP library suppressions (libcurl)
{
curl_global_init
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:curl_global_init
}
# Database driver suppressions (PostgreSQL)
{
postgresql_driver_init
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:PQconnectdb
}
# Custom application suppressions
{
app_singleton_leak
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:*Singleton*
}
# Logging framework suppressions
{
spdlog_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:*spdlog*
}
# Testing framework suppressions
{
googletest_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:*testing*
}
# Benchmark framework suppressions
{
benchmark_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:*benchmark*
}
# Docker/containerization suppressions
{
container_runtime_leak
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_dl_init
obj:*/ld-*.so
}
# Suppressions for specific architectures
{
x86_64_syscall_param
Memcheck:Param
syscall(write)
fun:write
fun:_IO_file_write@@GLIBC_*
}
{
arm64_specific_suppression
Memcheck:Cond
fun:__memcmp_sse4_1
fun:*
}
# Networking library suppressions
{
network_buffer_false_positive
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:*network*
fun:*socket*
}
# Regex library suppressions
{
regex_compilation_leak
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:_Znwm
fun:*regex*
}
# Crypto library suppressions
{
crypto_random_init
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:*random*
fun:*crypto*
}`;
}
static generateHelgrindSuppressions() {
return `# Valgrind Helgrind Suppressions
# Thread-related false positives
# Standard library thread suppressions
{
std_thread_false_positive
Helgrind:Race
fun:_ZNSt6thread*
}
{
std_mutex_false_positive
Helgrind:Race
fun:_ZNSt5mutex*
}
{
std_condition_variable_false_positive
Helgrind:Race
fun:_ZNSt18condition_variable*
}
# C++ atomics suppressions
{
atomic_operations_false_positive
Helgrind:Race
fun:*atomic*
}
# Thread-local storage
{
tls_access_false_positive
Helgrind:Race
fun:*thread_local*
}
# glibc thread suppressions
{
glibc_thread_init
Helgrind:Race
fun:pthread_create@@GLIBC_*
}
{
glibc_mutex_init
Helgrind:Race
fun:pthread_mutex_init
}
# Boost thread suppressions
{
boost_thread_library
Helgrind:Race
fun:_ZN5boost6thread*
}
{
boost_mutex_library
Helgrind:Race
fun:_ZN5boost5mutex*
}
# OpenMP suppressions
{
openmp_false_positive
Helgrind:Race
fun:*omp*
}
# Intel TBB suppressions
{
tbb_false_positive
Helgrind:Race
fun:*tbb*
}
# Logging library thread safety
{
spdlog_thread_safety
Helgrind:Race
fun:*spdlog*
}
# JSON library thread safety
{
json_thread_safety
Helgrind:Race
fun:*nlohmann*
}
# HTTP client thread safety
{
http_client_thread_safety
Helgrind:Race
fun:*curl*
}
# Database connection pool
{
db_connection_pool_race
Helgrind:Race
fun:*connection*
fun:*pool*
}
# Custom thread pool suppressions
{
custom_thread_pool_race
Helgrind:Race
fun:*ThreadPool*
}
# Signal handling suppressions
{
signal_handler_race
Helgrind:Race
fun:*signal*
}
# Memory allocator thread safety
{
allocator_thread_safety
Helgrind:Race
fun:malloc
fun:free
}
# Static initialization race
{
static_init_race
Helgrind:Race
fun:__static_initialization_and_destruction_*
}
# Destructor race conditions
{
destructor_race
Helgrind:Race
fun:__cxa_finalize
}
# Exception handling races
{
exception_handling_race
Helgrind:Race
fun:__cxa_throw
}
# RTTI race conditions
{
rtti_race
Helgrind:Race
fun:__dynamic_cast
}
# Stream operations race
{
stream_operations_race
Helgrind:Race
fun:*iostream*
}
# Locale operations race
{
locale_operations_race
Helgrind:Race
fun:*locale*
}
# Time operations race
{
time_operations_race
Helgrind:Race
fun:*time*
}
# Random number generation race
{
random_generation_race
Helgrind:Race
fun:*random*
}
# Filesystem operations race
{
filesystem_operations_race
Helgrind:Race
fun:*filesystem*
}`;
}
static generateValgrindScript(projectName, options) {
return `#!/bin/bash
# Comprehensive Valgrind Analysis Script for ${projectName}
# Memory analysis, thread safety, and performance profiling
set -euo pipefail
# Configuration
PROJECT_NAME="${projectName}"
BUILD_DIR="build"
EXECUTABLE_PATH="./\${BUILD_DIR}/\${PROJECT_NAME}"
RESULTS_DIR="valgrind_results"
TIMESTAMP="\\$(date +%Y%m%d_%H%M%S)"
# Valgrind tools configuration
ENABLE_MEMCHECK=${options.enableMemcheck}
ENABLE_HELGRIND=${options.enableHelgrind}
ENABLE_CACHEGRIND=${options.enableCachegrind}
ENABLE_CALLGRIND=${options.enableCallgrind}
ENABLE_MASSIF=${options.enableMassif}
ENABLE_DRD=${options.enableDRD}
# Colors for output
RED='\\033[0;31m'
GREEN='\\033[0;32m'
BLUE='\\033[0;34m'
YELLOW='\\033[1;33m'
NC='\\033[0m' # No Color
# Create results directory
mkdir -p "\\${RESULTS_DIR}"
echo -e "\\${BLUE}=== Valgrind Analysis Suite for \${PROJECT_NAME} ===\\${NC}"
# Check if executable exists
if [[ ! -f "\\${EXECUTABLE_PATH}" ]]; then
echo -e "\\${RED}Error: Executable not found at \\${EXECUTABLE_PATH}\\${NC}"
echo "Please build the project first with debug symbols:"
echo "cmake -DCMAKE_BUILD_TYPE=Debug -B \\${BUILD_DIR}"
echo "cmake --build \\${BUILD_DIR}"
exit 1
fi
# Check if valgrind is available
if ! command -v valgrind &> /dev/null; then
echo -e "\\${RED}Error: Valgrind not found. Please install valgrind.\\${NC}"
exit 1
fi
# Common valgrind flags
COMMON_FLAGS=(
--verbose
--log-file="\\${RESULTS_DIR}/valgrind_\\${TIMESTAMP}.log"
--time-stamp=yes
--track-fds=yes
--trace-children=yes
)
# Function to run valgrind tool
run_valgrind_tool() {
local tool_name="\\$1"
local tool_flags="\\$2"
local output_file="\\$3"
echo -e "\\${YELLOW}Running \\${tool_name}...\\${NC}"
local start_time=\\$(date +%s)
if valgrind \\${COMMON_FLAGS[]} \\${tool_flags} \\${EXECUTABLE_PATH} > "\\${output_file}.stdout" 2> "\\${output_file}.stderr"; then
local end_time=\\$(date +%s)
local duration=\\$((end_time - start_time))
echo -e "\\${GREEN}\\${tool_name} completed successfully in \\${duration}s\\${NC}"
echo -e "Results saved to \\${output_file}.*"
return 0
else
echo -e "\\${RED}\\${tool_name} detected issues. Check \\${output_file}.stderr\\${NC}"
return 1
fi
}
# Memcheck - Memory error detection
if [[ "\\${ENABLE_MEMCHECK}" == "true" ]]; then
MEMCHECK_FLAGS=(
--tool=memcheck
--leak-check=full
--show-leak-kinds=all
--track-origins=yes
--show-reachable=yes
--error-exitcode=1
--gen-suppressions=all
--suppressions=valgrind/memcheck.supp
--xml=yes
--xml-file="\\${RESULTS_DIR}/memcheck_\\${TIMESTAMP}.xml"
)
run_valgrind_tool "Memcheck" "\\${MEMCHECK_FLAGS[ * ]}" "\\${RESULTS_DIR}/memcheck_\\${TIMESTAMP}"
MEMCHECK_EXIT_CODE=\\$?
fi
# Helgrind - Thread error detection
if [[ "\\${ENABLE_HELGRIND}" == "true" ]]; then
HELGRIND_FLAGS=(
--tool=helgrind
--history-level=full
--conflict-cache-size=1000000
--suppressions=valgrind/helgrind.supp
--xml=yes
--xml-file="\\${RESULTS_DIR}/helgrind_\\${TIMESTAMP}.xml"
)
run_valgrind_tool "Helgrind" "\\${HELGRIND_FLAGS[ * ]}" "\\${RESULTS_DIR}/helgrind_\\${TIMESTAMP}"
HELGRIND_EXIT_CODE=\\$?
fi
# Cachegrind - Cache profiling
if [[ "\\${ENABLE_CACHEGRIND}" == "true" ]]; then
CACHEGRIND_FLAGS=(
--tool=cachegrind
--cache-sim=yes
--branch-sim=yes
--cachegrind-out-file="\\${RESULTS_DIR}/cachegrind_\\${TIMESTAMP}.out"
)
run_valgrind_tool "Cachegrind" "\\${CACHEGRIND_FLAGS[ * ]}" "\\${RESULTS_DIR}/cachegrind_\\${TIMESTAMP}"
# Generate cachegrind annotation
if command -v cg_annotate &> /dev/null; then
echo -e "\\${YELLOW}Generating Cachegrind annotation...\\${NC}"
cg_annotate "\\${RESULTS_DIR}/cachegrind_\\${TIMESTAMP}.out" > "\\${RESULTS_DIR}/cachegrind_\\${TIMESTAMP}_annotation.txt"
fi
fi
# Callgrind - Call profiling
if [[ "\\${ENABLE_CALLGRIND}" == "true" ]]; then
CALLGRIND_FLAGS=(
--tool=callgrind
--dump-instr=yes
--collect-jumps=yes
--collect-systime=yes
--callgrind-out-file="\\${RESULTS_DIR}/callgrind_\\${TIMESTAMP}.out"
)
run_valgrind_tool "Callgrind" "\\${CALLGRIND_FLAGS[ * ]}" "\\${RESULTS_DIR}/callgrind_\\${TIMESTAMP}"
# Generate callgrind annotation
if command -v callgrind_annotate &> /dev/null; then
echo -e "\\${YELLOW}Generating Callgrind annotation...\\${NC}"
callgrind_annotate "\\${RESULTS_DIR}/callgrind_\\${TIMESTAMP}.out" > "\\${RESULTS_DIR}/callgrind_\\${TIMESTAMP}_annotation.txt"
fi
fi
# Massif - Heap profiling
if [[ "\\${ENABLE_MASSIF}" == "true" ]]; then
MASSIF_FLAGS=(
--tool=massif
--heap=yes
--stacks=yes
--depth=30
--threshold=0.1
--peak-inaccuracy=0.1
--time-unit=ms
--massif-out-file="\\${RESULTS_DIR}/massif_\\${TIMESTAMP}.out"
)
run_valgrind_tool "Massif" "\\${MASSIF_FLAGS[ * ]}" "\\${RESULTS_DIR}/massif_\\${TIMESTAMP}"
# Generate massif visualization
if command -v ms_print &> /dev/null; then
echo -e "\\${YELLOW}Generating Massif visualization...\\${NC}"
ms_print "\\${RESULTS_DIR}/massif_\\${TIMESTAMP}.out" > "\\${RESULTS_DIR}/massif_\\${TIMESTAMP}_graph.txt"
fi
fi
# DRD - Data race detection
if [[ "\\${ENABLE_DRD}" == "true" ]]; then
DRD_FLAGS=(
--tool=drd
--check-stack-var=yes
--exclusive-threshold=10
--segment-merging=yes
--shared-threshold=10
--xml=yes
--xml-file="\\${RESULTS_DIR}/drd_\\${TIMESTAMP}.xml"
)
run_valgrind_tool "DRD" "\\${DRD_FLAGS[ * ]}" "\\${RESULTS_DIR}/drd_\\${TIMESTAMP}"
DRD_EXIT_CODE=\\$?
fi
# Generate comprehensive report
echo -e "\\${BLUE}=== Generating Analysis Report ===\\${NC}"
if command -v python3 &> /dev/null; then
python3 scripts/valgrind_analysis.py \\
--results-dir "\\${RESULTS_DIR}" \\
--timestamp "\\${TIMESTAMP}" \\
--project-name "\\${PROJECT_NAME}" \\
--output "\\${RESULTS_DIR}/analysis_report_\\${TIMESTAMP}.html"
echo -e "\\${GREEN}Comprehensive report generated: \\${RESULTS_DIR}/analysis_report_\\${TIMESTAMP}.html\\${NC}"
fi
# Summary
echo -e "\\${BLUE}=== Valgrind Analysis Summary ===\\${NC}"
echo "Project: \\${PROJECT_NAME}"
echo "Timestamp: \\${TIMESTAMP}"
echo "Results directory: \\${RESULTS_DIR}"
echo ""
# Exit status summary
OVERALL_EXIT_CODE=0
if [[ "\\${ENABLE_MEMCHECK}" == "true" ]]; then
if [[ \\${MEMCHECK_EXIT_CODE;
-0;
}
}
exports.CppValgrindGenerator = CppValgrindGenerator;
-eq;
0;
;
then;
echo - e;
"\\${GREEN}✓ Memcheck: No memory errors detected\\${NC}";
echo - e;
"\\${RED}✗ Memcheck: Memory errors detected\\${NC}";
OVERALL_EXIT_CODE = 1;
fi;
fi;
if ([["\\${ENABLE_HELGRIND}" == "true"]])
;
then;
if ([[$, { HELGRIND_EXIT_CODE: -0 } - eq, 0]])
;
then;
echo - e;
"\\${GREEN}✓ Helgrind: No thread errors detected\\${NC}";
echo - e;
"\\${RED}✗ Helgrind: Thread errors detected\\${NC}";
OVERALL_EXIT_CODE = 1;
fi;
fi;
if ([["\\${ENABLE_DRD}" == "true"]])
;
then;
if ([[$, { DRD_EXIT_CODE: -0 } - eq, 0]])
;
then;
echo - e;
"\\${GREEN}✓ DRD: No data races detected\\${NC}";
echo - e;
"\\${RED}✗ DRD: Data races detected\\${NC}";
OVERALL_EXIT_CODE = 1;
fi;
fi;
echo;
"";
echo;
"For detailed analysis, check individual result files in \\${RESULTS_DIR}/";
if ([[$, { OVERALL_EXIT_CODE } - eq, 0]])
;
then;
echo - e;
"\\${GREEN}All Valgrind tools passed successfully!\\${NC}";
echo - e;
"\\${RED}Some Valgrind tools detected issues. Please review the results.\\${NC}";
fi;
exit;
$;
{
OVERALL_EXIT_CODE;
}
`;
}
private static generateValgrindAnalysis(): string {
return `;
!/usr/bin / env;
python3;
"";
";
Valgrind;
Analysis;
Tool;
Processes;
Valgrind;
output;
and;
generates;
comprehensive;
reports;
"";
";
var os = ;
var argparse = ;
as;
ET;
from;
module_1.default;
const module_1 = __importDefault(require());
const module_2 = __importDefault(require());
var re = ;
class ValgrindAnalyzer {
}
def;
__init__(self, results_dir, str, timestamp, str, project_name, str);
self.results_dir = results_dir;
self.timestamp = timestamp;
self.project_name = project_name;
self.analysis_results = {};
def;
parse_memcheck_xml(self, xml_file, str) - > module_2.default[str, Any];
"";
"Parse Memcheck XML output.";
"";
try { }
finally { }
tree = ET.parse(xml_file);
root = tree.getroot();
errors = [];
for (error in root.findall('.//error'))
: error_data = {
'kind': error.find('kind').text, if: error.find('kind'), is, not, None, else: '',
'what': error.find('what').text, if: error.find('what'), is, not, None, else: '',
'stack': []
};
#;
Parse;
stack;
trace;
stack = error.find('stack');
if (stack)
is;
not;
None: for (frame in stack.findall('frame'))
: frame_data = {};
if (frame.find('fn'))
is;
not;
None: frame_data['function'] = frame.find('fn').text;
if (frame.find('file'))
is;
not;
None: frame_data['file'] = frame.find('file').text;
if (frame.find('line'))
is;
not;
None: frame_data['line'] = frame.find('line').text;
error_data['stack'].append(frame_data);
errors.append(error_data);
return {
'tool': 'memcheck',
'errors': errors,
'error_count': len(errors)
};
except;
Exception;
print(f, "Error parsing Memcheck XML: {e}");
return { 'tool': 'memcheck', 'errors': [], 'error_count': 0 };
def;
parse_helgrind_xml(self, xml_file, str) - > module_2.default[str, Any];
"";
"Parse Helgrind XML output.";
"";
try { }
finally { }
tree = ET.parse(xml_file);
root = tree.getroot();
errors = [];
for (error in root.findall('.//error'))
: error_data = {
'kind': error.find('kind').text, if: error.find('kind'), is, not, None, else: '',
'what': error.find('what').text, if: error.find('what'), is, not, None, else: '',
'stack': []
};
#;
Parse;
stack;
trace;
stack = error.find('stack');
if (stack)
is;
not;
None: for (frame in stack.findall('frame'))
: frame_data = {};
if (frame.find('fn'))
is;
not;
None: frame_data['function'] = frame.find('fn').text;
if (frame.find('file'))
is;
not;
None: frame_data['file'] = frame.find('file').text;
if (frame.find('line'))
is;
not;
None: frame_data['line'] = frame.find('line').text;
error_data['stack'].append(frame_data);
errors.append(error_data);
return {
'tool': 'helgrind',
'errors': errors,
'error_count': len(errors)
};
except;
Exception;
print(f, "Error parsing Helgrind XML: {e}");
return { 'tool': 'helgrind', 'errors': [], 'error_count': 0 };
def;
parse_cachegrind_output(self, output_file, str) - > module_2.default[str, Any];
"";
"Parse Cachegrind output.";
"";
try { }
finally { }
with (open(output_file, 'r'))
: content = f.read();
#;
Extract;
summary;
statistics;
stats = {};
for (line in content.split('\\n'))
: if ('I refs:' in line)
: stats['instruction_refs'] = self.extract_number(line);
elif;
'I1 misses:' in line;
stats['l1_instruction_misses'] = self.extract_number(line);
elif;
'LLi misses:' in line;
stats['ll_instruction_misses'] = self.extract_number(line);
elif;
'D refs:' in line;
stats['data_refs'] = self.extract_number(line);
elif;
'D1 misses:' in line;
stats['l1_data_misses'] = self.extract_number(line);
elif;
'LLd misses:' in line;
stats['ll_data_misses'] = self.extract_number(line);
return {
'tool': 'cachegrind',
'stats': stats
};
except;
Exception;
print(f, "Error parsing Cachegrind output: {e}");
return { 'tool': 'cachegrind', 'stats': {} };
def;
parse_massif_output(self, output_file, str) - > module_2.default[str, Any];
"";
"Parse Massif output.";
"";
try { }
finally { }
with (open(output_file, 'r'))
: content = f.read();
#;
Extract;
memory;
usage;
statistics;
stats = {};
peak_usage = 0;
snapshots = [];
for (line in content.split('\\n'))
: if (line.startswith('mem_heap_B='))
: heap_usage = int(line.split('=')[1]);
peak_usage = max(peak_usage, heap_usage);
elif;
line.startswith('snapshot=');
snapshot_data = self.parse_massif_snapshot(line);
if (snapshot_data)
: snapshots.append(snapshot_data);
stats['peak_heap_usage'] = peak_usage;
stats['snapshots'] = snapshots;
return {
'tool': 'massif',
'stats': stats
};
except;
Exception;
print(f, "Error parsing Massif output: {e}");
return { 'tool': 'massif', 'stats': {} };
def;
extract_number(self, line, str) - > int;
"";
"Extract number from line with commas.";
"";
match = re.search(r, '([0-9,]+)', line);
if (match)
: return int(match.group(1).replace(',', ''));
return 0;
def;
parse_massif_snapshot(self, line, str) - > Optional[module_2.default[str, Any]];
"";
"Parse Massif snapshot line.";
"";
try { }
finally { }
parts = line.split('=');
if (len(parts) >= 2)
: return {
'snapshot': int(parts[1].split('#')[0]),
'time': parts[2], if: len(parts) > 2, else: 0
};
except: pass;
return None;
def;
analyze_results(self);
"";
"Analyze all available Valgrind results.";
"";
#;
Check;
for (Memcheck; results; memcheck_xml = os.path.join(self.results_dir, f, 'memcheck_{self.timestamp}.xml'))
if (os.path.exists(memcheck_xml))
: self.analysis_results['memcheck'] = self.parse_memcheck_xml(memcheck_xml);
#;
Check;
for (Helgrind; results; helgrind_xml = os.path.join(self.results_dir, f, 'helgrind_{self.timestamp}.xml'))
if (os.path.exists(helgrind_xml))
: self.analysis_results['helgrind'] = self.parse_helgrind_xml(helgrind_xml);
#;
Check;
for (Cachegrind; results; cachegrind_out = os.path.join(self.results_dir, f, 'cachegrind_{self.timestamp}.out'))
if (os.path.exists(cachegrind_out))
: self.analysis_results['cachegrind'] = self.parse_cachegrind_output(cachegrind_out);
#;
Check;
for (Massif; results; massif_out = os.path.join(self.results_dir, f, 'massif_{self.timestamp}.out'))
if (os.path.exists(massif_out))
: self.analysis_results['massif'] = self.parse_massif_output(massif_out);
def;
generate_html_report(self, output_file, str);
"";
"Generate comprehensive HTML report.";
"";
html_content = f;
"";
"
< !DOCTYPE;
html >
Valgrind;
Analysis;
Report - { self, : .project_name } < (/title>);
body;
{
{
font - family;
Arial, sans - serif;
margin: 20;
px;
}
}
header;
{
{
background - color;
#f0f0f0;
padding: 20;
px;
border - radius;
5;
px;
}
}
section;
{
{
margin: 20;
px;
0;
padding: 15;
px;
border: 1;
px;
solid;
#ddd;
border - radius;
5;
px;
}
}
error;
{
{
background - color;
#ffebee;
border - left;
4;
px;
solid;
#f44336;
}
}
warning;
{
{
background - color;
#fff3e0;
border - left;
4;
px;
solid;
#ff9800;
}
}
success;
{
{
background - color;
#e8f5e8;
border - left;
4;
px;
solid;
#;
4;
caf50;
}
}
info;
{
{
background - color;
#e3f2fd;
border - left;
4;
px;
solid;
#;
2196;
f3;
}
}
stack - trace;
{
{
background - color;
#f5f5f5;
padding: 10;
px;
font - family;
monospace;
}
}
table;
{
{
border - collapse;
collapse;
width: 100 % ;
}
}
th, td;
{
{
border: 1;
px;
solid;
#ddd;
padding: 8;
px;
text - align;
left;
}
}
th;
{
{
background - color;
#f2f2f2;
}
}
metric;
{
{
font - size;
1.2e;
m;
font - weight;
bold;
}
}
/style>
< /head>
< body >
class {
};
"header" >
Valgrind;
Analysis;
Report < /h1>
< p > Project;
/strong> {self.project_name}</p >
Timestamp;
/strong> {self.timestamp}</p >
Generated;
/strong> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p >
/div>;
"";
";
#;
Executive;
Summary;
html_content += self.generate_executive_summary();
#;
Detailed;
results;
for (each; tool; )
for (tool, results in self.analysis_results.items())
: html_content += self.generate_tool_section(tool, results);
#;
Recommendations;
html_content += self.generate_recommendations();
html_content += "";
"
< /body>
< /html>;
"";
";
with (open(output_file, 'w'))
: f.write(html_content);
def;
generate_executive_summary(self) - > str;
"";
"Generate executive summary section.";
"";
total_errors = 0;
tools_run = [];
for (tool, results in self.analysis_results.items())
: tools_run.append(tool);
if ('error_count' in results)
: total_errors += results['error_count'];
status_class = 'success';
if (total_errors == 0)
;
else
'error';
return f;
"";
"
< div;
class {
}
"section {status_class}" >
Executive;
Summary < /h2>
< p > class {
};
"metric" > Total;
Errors: {
total_errors;
}
/span></p >
Tools;
Run: /strong> {', '.join(tools_run)}</p >
Status;
/strong> {'✓ Clean' if total_errors == 0 else '✗ Issues Found'}</p >
/div>;
"";
";
def;
generate_tool_section(self, tool, str, results, module_2.default[str, Any]) - > str;
"";
"Generate section for specific tool results.";
"";
if (tool == 'memcheck')
: return self.generate_memcheck_section(results);
elif;
tool == 'helgrind';
return self.generate_helgrind_section(results);
elif;
tool == 'cachegrind';
return self.generate_cachegrind_section(results);
elif;
tool == 'massif';
return self.generate_massif_section(results);
return f;
'<div class="section info"><h3>{tool.title()}</h3><p>Results available</p></div>';
def;
generate_memcheck_section(self, results, module_2.default[str, Any]) - > str;
"";
"Generate Memcheck results section.";
"";
error_count = results.get('error_count', 0);
status_class = 'success';
if (error_count == 0)
;
else
'error';
content = f;
"";
"
< div;
class {
}
"section {status_class}" >
Memcheck;
Results < /h2>
< p > class {
};
"metric" > Memory;
Errors: {
error_count;
}
/span></p >
"";
";
if (error_count > 0)
: content += "<h3>Error Details</h3>";
for (i, error in enumerate(results.get('errors', [])[], 10))
: #;
Show;
first;
10;
errors;
content += f;
"";
"
< div;
class {
}
"error" >
Error;
{
i + 1;
}
{
error.get('kind', 'Unknown');
}
/h4>
< p > { error, : .get('what', 'No description') } < /p>;
"";
";
if (error.get('stack'))
: content += '<div class="stack-trace">';
for (frame in error['stack'][])
: 5;
#;
Show;
first;
5;
frames;
func = frame.get('function', 'Unknown');
file_line = f;
"{frame.get('file', 'Unknown')}:{frame.get('line', '?')}";
content += f;
" {func} ({file_line})<br>";
content += '</div>';
content += '</div>';
content += '</div>';
return content;
def;
generate_helgrind_section(self, results, module_2.default[str, Any]) - > str;
"";
"Generate Helgrind results section.";
"";
error_count = results.get('error_count', 0);
status_class = 'success';
if (error_count == 0)
;
else
'error';
return f;
"";
"
< div;
class {
}
"section {status_class}" >
Helgrind;
Results < /h2>
< p > class {
};
"metric" > Thread;
Errors: {
error_count;
}
/span></p >
{ '<p>No thread safety issues detected.</p>': , if: error_count == 0, else: '<p>Thread safety issues detected. Check detailed logs.</p>' }
< /div>;
"";
";
def;
generate_cachegrind_section(self, results, module_2.default[str, Any]) - > str;
"";
"Generate Cachegrind results section.";
"";
stats = results.get('stats', {});
content = "";
"
< div;
class {
}
"section info" >
Cachegrind;
Results < /h2>
< table >
Metric < /th><th>Value</th > /tr>;
"";
";
for (metric, value in stats.items())
: formatted_value = f;
"{value:,}";
if (isinstance(value, int))
;
else
str(value);
content += f;
"<tr><td>{metric.replace('_', ' ').title()}</td><td>{formatted_value}</td></tr>";
content += "";
"
< /table>
< /div>;
"";
";
return content;
def;
generate_massif_section(self, results, module_2.default[str, Any]) - > str;
"";
"Generate Massif results section.";
"";
stats = results.get('stats', {});
peak_usage = stats.get('peak_heap_usage', 0);
return f;
"";
"
< div;
class {
}
"section info" >
Massif;
Results < /h2>
< p > class {
};
"metric" > Peak;
Heap;
Usage: {
peak_usage: , ;
}
bytes < /span></p >
class {
};
"metric" > Peak;
Heap;
Usage: {
peak_usage / 1024 / 1024;
.2;
f;
}
MB < /span></p >
Snapshots;
{
len(stats.get('snapshots', []));
}
/p>
< /div>;
"";
";
def;
generate_recommendations(self) - > str;
"";
"Generate recommendations section.";
"";
recommendations = [];
#;
Check;
for (memory; errors; )
if ('memcheck' in self.analysis_results)
: error_count = self.analysis_results['memcheck'].get('error_count', 0);
if (error_count > 0)
: recommendations.append("Fix memory leaks and invalid memory accesses detected by Memcheck");
#;
Check;
for (thread; errors; )
if ('helgrind' in self.analysis_results)
: error_count = self.analysis_results['helgrind'].get('error_count', 0);
if (error_count > 0)
: recommendations.append("Address thread safety issues detected by Helgrind");
#;
Performance;
recommendations;
if ('cachegrind' in self.analysis_results)
: recommendations.append("Review cache usage patterns for performance optimization");
if ('massif' in self.analysis_results)
: recommendations.append("Monitor heap usage patterns for memory optimization");
if (not)
recommendations: recommendations.append("No issues detected. Continue with regular monitoring.");
content = "";
"
< div;
class {
}
"section warning" >
Recommendations < (/h2>);
"";
";
for (rec in recommendations)
: content += f;
"<li>{rec}</li>";
content += "";
"
< /ul>
< /div>;
"";
";
return content;
def;
main();
parser = argparse.ArgumentParser(description = 'Analyze Valgrind results');
parser.add_argument('--results-dir', required = True, help = 'Directory containing Valgrind results');
parser.add_argument('--timestamp', required = True, help = 'Timestamp for result files');
parser.add_argument('--project-name', required = True, help = 'Project name');
parser.add_argument('--output', required = True, help = 'Output HTML file');
args = parser.parse_args();
analyzer = ValgrindAnalyzer(args.results_dir, args.timestamp, args.project_name);
analyzer.analyze_results();
analyzer.generate_html_report(args.output);
print(f, "Analysis complete. Report saved to {args.output}");
if (__name__ == '__main__')
: main() `;
}
private static generateValgrindReadme(projectName: string): string {
return `;
#;
Valgrind;
Memory;
Analysis;
for ($; { projectName }; This)
directory;
contains;
Valgrind;
configuration;
and;
tools;
for (comprehensive; memory; analysis)
and;
debugging.
;
#;
#;
Overview;
Valgrind;
is;
a;
powerful;
suite;
of;
tools;
for (debugging; and; profiling)
programs: - ** Memcheck ** ;
Memory;
error;
detection(leaks, invalid, accesses, uninitialized, memory)
- ** Helgrind ** ;
Thread;
error;
detection(race, conditions, deadlocks)
- ** Cachegrind ** ;
Cache;
profiling;
and;
performance;
analysis
- ** Callgrind ** ;
Call;
profiling;
and;
performance;
analysis
- ** Massif ** ;
Heap;
profiling;
and;
memory;
usage;
analysis
- ** DRD ** ;
Alternative;
thread;
error;
detection;
#;
#;
Quick;
Start;
#;
#;
#;
Building;
for (Valgrind; ; )
;
`\`\`bash
# Build with debug symbols and no optimization
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_VALGRIND=ON
cmake --build build
\`\`\`
### Running Analysis
\`\`\`bash
# Run comprehensive analysis
./scripts/run_valgrind.sh
# Run specific tool
valgrind --tool=memcheck --leak-check=full ./build/${projectName}
# Run with CMake/CTest
ctest -R valgrind
\`\`\`
## Tools Overview
### Memcheck - Memory Error Detection
**Purpose**: Detect memory leaks, buffer overflows, use of uninitialized memory
**Common Issues Detected**:
- Memory leaks (heap, stack)
- Invalid memory accesses
- Use of uninitialized memory
- Double free errors
- Mismatched malloc/free and new/delete
**Usage**:
\`\`\`bash
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./build/${projectName}
\`\`\`
### Helgrind - Thread Error Detection
**Purpose**: Detect race conditions and threading issues
**Common Issues Detected**:
- Data races
- Lock ordering problems
- Misuse of POSIX pthreads API
- Inconsistent lock acquisition
**Usage**:
\`\`\`bash
valgrind --tool=helgrind ./build/${projectName}
\`\`\`
### Cachegrind - Cache Profiling
**Purpose**: Analyze cache usage and performance
**Metrics Provided**:
- L1/L2/L3 cache misses
- Branch misprediction rates
- Instruction execution counts
**Usage**:
\`\`\`bash
valgrind --tool=cachegrind ./build/${projectName}
# View results
cg_annotate cachegrind.out.{pid}
\`\`\`
### Massif - Heap Profiling
**Purpose**: Analyze heap memory usage over time
**Features**:
- Heap usage snapshots
- Memory allocation patterns
- Peak memory usage identification
**Usage**:
\`\`\`bash
valgrind --tool=massif ./build/${projectName}
# View results
ms_print massif.out.{pid}
\`\`\`
## Configuration Files
### Suppression Files
- \`memcheck.supp\`: Suppresses known false positives in Memcheck
- \`helgrind.supp\`: Suppresses known false positives in Helgrind
### Tool Configuration
- \`configs/memcheck.conf\`: Memcheck-specific settings
- \`configs/helgrind.conf\`: Helgrind-specific settings
- \`configs/cachegrind.conf\`: Cachegrind-specific settings
- \`configs/massif.conf\`: Massif-specific settings
## Integration with Build System
### CMake Integration
The project includes CMake functions for easy Valgrind integration:
\`\`\`cmake
# Add Valgrind tests for an executable
add_valgrind_test(my_executable MEMCHECK HELGRIND)
# Add Valgrind flags to a target
add_valgrind_flags(my_target)
# Enable Valgrind for all targets
enable_valgrind_for_target(my_target)
\`\`\`
### CTest Integration
Run Valgrind tests through CTest:
\`\`\`bash
# Run all Valgrind tests
ctest -R valgrind
# Run specific tool tests
ctest -R valgrind_memcheck
ctest -R valgrind_helgrind
\`\`\`
## Continuous Integration
### GitHub Actions
The project includes GitHub Actions workflow for automated Valgrind analysis:
- Runs on pull requests and main branch
- Detects memory leaks and thread errors
- Generates detailed reports
- Fails builds on critical issues
### Docker Support
Use the provided Docker image for consistent analysis:
\`\`\`bash
# Build Valgrind Docker image
docker build -f valgrind/docker/Dockerfile.valgrind -t ${projectName}-valgrind .
# Run analysis in container
docker run --rm -v \$(pwd):/workspace ${projectName}-valgrind
\`\`\`
## Analysis and Reporting
### Automated Analysis
The \`valgrind_analysis.py\` script provides:
- XML report parsing
- HTML report generation
- Error categorization and prioritization
- Performance metrics analysis
### Memory Report Generation
\`\`\`bash
# Generate comprehensive memory report
python3 scripts/memory_report.py --results-dir valgrind_results
\`\`\`
## Best Practices
### Writing Valgrind-Friendly Code
1. **Use RAII**: Ensure automatic cleanup of resources
2. **Initialize variables**: Avoid uninitialized memory access
3. **Proper synchronization**: Use mutexes and locks correctly
4. **Avoid raw pointers**: Use smart pointers when possible
### Debugging with Valgrind
1. **Build with debug symbols**: Use \`-g\` flag
2. **Disable optimization**: Use \`-O0\` for accurate results
3. **Use suppressions**: Filter out known false positives
4. **Start with Memcheck**: Address memory issues first
### Performance Considerations
- Valgrind slows down execution 10-50x
- Use suppressions to reduce noise
- Run on representative workloads
- Focus on critical code paths
## Troubleshooting
### Common Issues
1. **False positives**: Add suppressions for known issues
2. **Slow execution**: Use minimal test cases
3. **Missing debug info**: Ensure debug symbols are included
4. **System library issues**: Use system-specific suppressions
### Debugging Tips
\`\`\`bash
# Get more detailed output
valgrind --verbose --track-origins=yes
# Generate suppressions automatically
valgrind --gen-suppressions=all
# Increase verbosity for debugging
valgrind --verbose --trace-children=yes
\`\`\`
## Integration with IDEs
### Visual Studio Code
Add launch configuration for Valgrind debugging:
\`\`\`json
{
"name": "Valgrind Debug",
"type": "cppdbg",
"request": "launch",
"program": "valgrind",
"args": ["--tool=memcheck", "--leak-check=full", "./build/${projectName}"],
"stopAtEntry": false,
"cwd": "\${workspaceFolder}",
"environment": [],
"externalConsole": false
}
\`\`\`
### CLion
Configure Valgrind as external tool:
1. Go to File → Settings → Tools → External Tools
2. Add new tool with Valgrind configuration
3. Use custom run configuration
## Resources
- [Valgrind Documentation](https://valgrind.org/docs/)
- [Memcheck Manual](https://valgrind.org/docs/manual/mc-manual.html)
- [Helgrind Manual](https://valgrind.org/docs/manual/hg-manual.html)
- [Performance Analysis Guide](https://valgrind.org/docs/manual/manual-core.html)`;
generateValgrindCI(projectName, string);
string;
{
return `name: Valgrind Memory Analysis
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
# Run nightly analysis at 3 AM UTC
- cron: '0 3 * * *'
env:
BUILD_TYPE: Debug
jobs:
valgrind-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \\
valgrind \\
cmake \\
ninja-build \\
gcc-11 \\
g++-11 \\
python3-pip \\
python3-lxml
pip3 install matplotlib seaborn pandas
- name: Configure CMake
run: |
cmake -B build \\
-DCMAKE_BUILD_TYPE=\\${{ env, : .BUILD_TYPE }} \\
-DCMAKE_CXX_COMPILER=g++-11 \\
-DCMAKE_C_COMPILER=gcc-11 \\
-DENABLE_VALGRIND=ON \\
-GNinja
- name: Build
run: cmake --build build --config \\${{ env, : .BUILD_TYPE }}
- name: Run Valgrind Memcheck
run: |
mkdir -p valgrind_results
# Run Memcheck
valgrind \\
--tool=memcheck \\
--leak-check=full \\
--show-leak-kinds=all \\
--track-origins=yes \\
--verbose \\
--xml=yes \\
--xml-file=valgrind_results/memcheck.xml \\
--error-exitcode=1 \\
--suppressions=valgrind/memcheck.supp \\
./build/${projectName} \\
2>&1 | tee valgrind_results/memcheck.log
continue-on-error: true
id: memcheck
- name: Run Valgrind Helgrind
run: |
# Run Helgrind (thread error detection)
valgrind \\
--tool=helgrind \\
--verbose \\
--xml=yes \\
--xml-file=valgrind_results/helgrind.xml \\
--error-exitcode=1 \\
--suppressions=valgrind/helgrind.supp \\
./build/${projectName} \\
2>&1 | tee valgrind_results/helgrind.log
continue-on-error: true
id: helgrind
- name: Run Valgrind Cachegrind
run: |
# Run Cachegrind (cache profiling)
valgrind \\
--tool=cachegrind \\
--verbose \\
--cachegrind-out-file=valgrind_results/cachegrind.out \\
./build/${projectName} \\
2>&1 | tee valgrind_results/cachegrind.log
# Generate annotation if available
if command -v cg_annotate &> /dev/null; then
cg_annotate valgrind_results/cachegrind.out > valgrind_results/cachegrind_annotation.txt
fi
continue-on-error: true
- name: Run Valgrind Massif
run: |
# Run Massif (heap profiling)
valgrind \\
--tool=massif \\
--verbose \\
--massif-out-file=valgrind_results/massif.out \\
--heap=yes \\
--stacks=yes \\
--time-unit=ms \\
./build/${projectName} \\
2>&1 | tee valgrind_results/massif.log
# Generate visualization if available
if command -v ms_print &> /dev/null; then
ms_print valgrind_results/massif.out > valgrind_results/massif_graph.txt
fi
continue-on-error: true
- name: Generate Analysis Report
run: |
# Generate comprehensive analysis report
python3 scripts/valgrind_analysis.py \\
--results-dir valgrind_results \\
--timestamp \\$(date +%Y%m%d_%H%M%S) \\