diff --git a/cmake/Modules/Testing.cmake b/cmake/Modules/Testing.cmake index 732613605ea..e83fc940343 100644 --- a/cmake/Modules/Testing.cmake +++ b/cmake/Modules/Testing.cmake @@ -11,7 +11,11 @@ if(ENABLE_TESTING) file(READ ${SUPP} SUPPRESSIONS) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/lammps.supp "${SUPPRESSIONS}") endforeach() - set(VALGRIND_DEFAULT_OPTIONS "--leak-check=full --show-leak-kinds=all --track-origins=yes --suppressions=${CMAKE_BINARY_DIR}/lammps.supp") + # blocks that are still reachable when the process exits are not leaks. reporting + # them buries the actual defects under thousands of one-time initializations in + # OpenSSL, libcurl, CPython, and GoogleTest, plus everything that is still in use + # when a command like "quit" or an error exit terminates the process on purpose. + set(VALGRIND_DEFAULT_OPTIONS "--leak-check=full --show-leak-kinds=definite,indirect,possible --track-origins=yes --suppressions=${CMAKE_BINARY_DIR}/lammps.supp") set(MEMORYCHECK_COMMAND "${VALGRIND_BINARY}" CACHE FILEPATH "Memory Check Command") set(MEMORYCHECK_COMMAND_OPTIONS "${VALGRIND_DEFAULT_OPTIONS}" CACHE STRING "Memory Check Command Options") diff --git a/src/DIFFRACTION/compute_saed.cpp b/src/DIFFRACTION/compute_saed.cpp index c84f4c146f0..9a1108de064 100644 --- a/src/DIFFRACTION/compute_saed.cpp +++ b/src/DIFFRACTION/compute_saed.cpp @@ -55,7 +55,7 @@ ComputeSAED::ComputeSAED(LAMMPS *lmp, int narg, char **arg) : nlocalgroup = 0; if (lmp->citeme) lmp->citeme->add(cite_compute_saed_c); - int ntypes = atom->ntypes; + ntypes = atom->ntypes; int natoms = group->count(igroup); int dimension = domain->dimension; int *periodicity = domain->periodicity; diff --git a/src/DIFFRACTION/compute_xrd.cpp b/src/DIFFRACTION/compute_xrd.cpp index 18fb8a25866..6e4594f5064 100644 --- a/src/DIFFRACTION/compute_xrd.cpp +++ b/src/DIFFRACTION/compute_xrd.cpp @@ -56,7 +56,7 @@ ComputeXRD::ComputeXRD(LAMMPS *lmp, int narg, char **arg) : nlocalgroup = 0; if (lmp->citeme) lmp->citeme->add(cite_compute_xrd_c); - int ntypes = atom->ntypes; + ntypes = atom->ntypes; int natoms = group->count(igroup); int dimension = domain->dimension; int *periodicity = domain->periodicity; diff --git a/src/DPD-MESO/pair_edpd.cpp b/src/DPD-MESO/pair_edpd.cpp index 2df3bea181f..e8e7c4e534f 100644 --- a/src/DPD-MESO/pair_edpd.cpp +++ b/src/DPD-MESO/pair_edpd.cpp @@ -283,6 +283,7 @@ void PairEDPD::settings(int narg, char **arg) delete random; random = new RanMars(lmp,(seed + comm->me) % 900000000); + delete randomT; randomT = new RanMars(lmp,(2*seed + comm->me) % 900000000); // reset cutoffs that have been explicitly set diff --git a/src/DPD-SMOOTH/pair_sdpd_taitwater_isothermal.cpp b/src/DPD-SMOOTH/pair_sdpd_taitwater_isothermal.cpp index 1716fb99a45..e686c075433 100644 --- a/src/DPD-SMOOTH/pair_sdpd_taitwater_isothermal.cpp +++ b/src/DPD-SMOOTH/pair_sdpd_taitwater_isothermal.cpp @@ -259,6 +259,7 @@ void PairSDPDTaitwaterIsothermal::settings (int narg, char **arg) { #ifdef USE_ZEST generator.seed (seed); #else + delete random; random = new RanMars (lmp, seed); #endif } diff --git a/src/EFF/pair_eff_cut.h b/src/EFF/pair_eff_cut.h index 89c9376c0af..f76de25dc03 100644 --- a/src/EFF/pair_eff_cut.h +++ b/src/EFF/pair_eff_cut.h @@ -49,9 +49,12 @@ class PairEffCut : public Pair { int ecp_found; double cut_global; double **cut; - int ecp_type[100]; - double PAULI_CORE_A[100], PAULI_CORE_B[100], PAULI_CORE_C[100]; - double PAULI_CORE_D[100], PAULI_CORE_E[100]; + // only the entries of ECP types set with the "ecp" keyword are filled in, + // but write_restart_settings() stores the arrays as a whole, so they must + // not contain uninitialized data + int ecp_type[100] = {}; + double PAULI_CORE_A[100] = {}, PAULI_CORE_B[100] = {}, PAULI_CORE_C[100] = {}; + double PAULI_CORE_D[100] = {}, PAULI_CORE_E[100] = {}; double hhmss2e, h2e; int nmax; diff --git a/src/KSPACE/pppm.cpp b/src/KSPACE/pppm.cpp index 5af807113fb..04eb0195ef9 100644 --- a/src/KSPACE/pppm.cpp +++ b/src/KSPACE/pppm.cpp @@ -98,7 +98,7 @@ PPPM::PPPM(LAMMPS *lmp) : KSpace(lmp), MPI_Comm_rank(world,&me); MPI_Comm_size(world,&nprocs); - nfft_both = 0; + ngrid = nfft_both = 0; nxhi_in = nxlo_in = nxhi_out = nxlo_out = 0; nyhi_in = nylo_in = nyhi_out = nylo_out = 0; nzhi_in = nzlo_in = nzhi_out = nzlo_out = 0; diff --git a/src/KSPACE/pppm_dipole_spin.cpp b/src/KSPACE/pppm_dipole_spin.cpp index 40a6dda9d41..c89fb2b8b0a 100644 --- a/src/KSPACE/pppm_dipole_spin.cpp +++ b/src/KSPACE/pppm_dipole_spin.cpp @@ -202,6 +202,19 @@ void PPPMDipoleSpin::init() double estimated_accuracy = final_accuracy_dipole(); + // allocate K-space dependent memory + // don't invoke allocate peratom(), will be allocated when needed + // must happen before printing the stats below, since allocate() + // is what sets ngrid and nfft_both + + allocate(); + + // pre-compute Green's function denominator expansion + // pre-compute 1d charge distribution coefficients + + compute_gf_denom(); + compute_rho_coeff(); + // print stats int ngrid_max,nfft_both_max; @@ -221,17 +234,6 @@ void PPPMDipoleSpin::init() ngrid_max,nfft_both_max); utils::logmesg(lmp,mesg); } - - // allocate K-space dependent memory - // don't invoke allocate peratom(), will be allocated when needed - - allocate(); - - // pre-compute Green's function denominator expansion - // pre-compute 1d charge distribution coefficients - - compute_gf_denom(); - compute_rho_coeff(); } /* ---------------------------------------------------------------------- diff --git a/src/MANYBODY/pair_local_density.cpp b/src/MANYBODY/pair_local_density.cpp index 411f357bd1b..d785c2ef697 100644 --- a/src/MANYBODY/pair_local_density.cpp +++ b/src/MANYBODY/pair_local_density.cpp @@ -690,6 +690,22 @@ void PairLocalDensity::parse_file(char *filename) { double *ftmp; // tmp var to extract the complete 2D frho array from file // setting up all arrays to be read from files and broadcasted + // free any storage from a previous pair_coeff command first + + memory->destroy(uppercut); + memory->destroy(lowercut); + memory->destroy(uppercutsq); + memory->destroy(lowercutsq); + memory->destroy(c0); + memory->destroy(c2); + memory->destroy(c4); + memory->destroy(c6); + memory->destroy(rho_min); + memory->destroy(rho_max); + memory->destroy(delta_rho); + memory->destroy(a); + memory->destroy(b); + memory->create(uppercut, nLD, "pairLD:uppercut"); memory->create(lowercut, nLD, "pairLD:lowercut"); memory->create(uppercutsq, nLD, "pairLD:uppercutsq"); @@ -804,6 +820,8 @@ void PairLocalDensity::parse_file(char *filename) { MPI_Bcast(&ftmp[0], nLD*nrho, MPI_DOUBLE, 0, world); // set up rho and frho arrays + memory->destroy(rho); + memory->destroy(frho); memory->create(rho, nLD, nrho, "pairLD:rho"); memory->create(frho, nLD, nrho, "pairLD:frho"); diff --git a/src/MC/pair_dsmc.cpp b/src/MC/pair_dsmc.cpp index 73f5eb7fc7c..ab50a29836a 100644 --- a/src/MC/pair_dsmc.cpp +++ b/src/MC/pair_dsmc.cpp @@ -293,6 +293,12 @@ void PairDSMC::init_style() total_ncells = ncellsx*ncellsy*ncellsz; vol = cellx*celly*cellz; + // free storage from a previous init_style() call + + memory->destroy(particle_list); + memory->destroy(first); + memory->destroy(number); + memory->create(particle_list,atom->ntypes+1,0,"pair:particle_list"); memory->create(first,atom->ntypes+1,total_ncells,"pair:first"); memory->create(number,atom->ntypes+1,total_ncells,"pair:number"); diff --git a/src/ML-QUIP/pair_quip.cpp b/src/ML-QUIP/pair_quip.cpp index 7f8e6fd6af8..dc70794846b 100644 --- a/src/ML-QUIP/pair_quip.cpp +++ b/src/ML-QUIP/pair_quip.cpp @@ -251,7 +251,9 @@ void PairQUIP::coeff(int narg, char **arg) } // use expanded file name, including LAMMPS_POTENTIALS search path + delete[] quip_file; quip_file = utils::strdup(utils::get_potential_file_path(arg[2])); + delete[] quip_string; quip_string = utils::strdup(arg[3]); n_quip_file = strlen(quip_file); n_quip_string = strlen(quip_string); @@ -286,6 +288,7 @@ void PairQUIP::coeff(int narg, char **arg) // and returns the necessary size of quip_potential. This behavior // is invoked by setting n_potential_quip to 0. n_quip_potential = 0; + delete[] quip_potential; quip_potential = new int[1]; quip_lammps_potential_initialise(quip_potential, &n_quip_potential, &cutoff, quip_file, &n_quip_file, quip_string, &n_quip_string); diff --git a/src/OPENMP/pair_local_density_omp.cpp b/src/OPENMP/pair_local_density_omp.cpp index 909569c7fdc..5b2fab5e330 100644 --- a/src/OPENMP/pair_local_density_omp.cpp +++ b/src/OPENMP/pair_local_density_omp.cpp @@ -73,6 +73,15 @@ void PairLocalDensityOMP::compute(int eflag, int vflag) for (int k = 0; k < nLD; k++) memset(&localrho[k][tid*nall], 0, nall * sizeof(double)); + // zero fp. pass 2 assigns it only for those local densities that apply + // to the type of the central atom, while pass 3 reads all of them. + // fp is shared, so each thread only zeroes its own chunk of atoms. + + int kfrom, kto; + loop_setup_thr(kfrom, kto, tid, nall, nthreads); + for (int k = 0; k < nLD; k++) + memset(&fp[k][kfrom], 0, (kto-kfrom) * sizeof(double)); + // ------------------------------------------------------------------- // Pass 1: compute per-thread local densities diff --git a/src/SPIN/fix_nve_spin.cpp b/src/SPIN/fix_nve_spin.cpp index 8a12f715d5e..9eae606ba0c 100644 --- a/src/SPIN/fix_nve_spin.cpp +++ b/src/SPIN/fix_nve_spin.cpp @@ -297,6 +297,7 @@ void FixNVESpin::init() // setting the sector variables/lists nsectors = 0; + memory->destroy(rsec); memory->create(rsec,3,"nve/spin:rsec"); // perform the sectoring operation diff --git a/src/atom_vec_ellipsoid.cpp b/src/atom_vec_ellipsoid.cpp index d520bf88b52..3a015e00130 100644 --- a/src/atom_vec_ellipsoid.cpp +++ b/src/atom_vec_ellipsoid.cpp @@ -682,6 +682,10 @@ void AtomVecEllipsoid::data_atom_post(int ilocal) if (rmass[ilocal] <= 0.0) error->one(FLERR, "Invalid density in Atoms section of data file"); + // data_atom_bonus() overrides this for atoms listed in the Ellipsoids section + + if (atom->superellipsoid_flag) radius[ilocal] = 0.0; + angmom[ilocal][0] = 0.0; angmom[ilocal][1] = 0.0; angmom[ilocal][2] = 0.0; diff --git a/src/delete_atoms.cpp b/src/delete_atoms.cpp index 2c366a73bcd..7ab1dfc7c4b 100644 --- a/src/delete_atoms.cpp +++ b/src/delete_atoms.cpp @@ -237,6 +237,13 @@ void DeleteAtoms::command(int narg, char **arg) // overwrite tags with condensed values for (int i = 0; i < nlocal; ++i) tag[i] = newtags[i]; + // tagproc is only needed by the settags() callback above + // newtags points to mynewtags and thus must not be deleted + + delete[] tagproc; + tagproc = nullptr; + newtags = nullptr; + // update atom map since we changed the tags atom->map_tag_max = -1; atom->map_style_set(); diff --git a/tools/valgrind/README b/tools/valgrind/README index 1b53347c480..b1402624420 100644 --- a/tools/valgrind/README +++ b/tools/valgrind/README @@ -5,7 +5,8 @@ and fixing real issues. When using CMake, these are automatically included when running "ctest -T memcheck". To manually add them to do a memory check on running LAMMPS, use a command line like following: -valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \ +valgrind --leak-check=full --track-origins=yes \ + --show-leak-kinds=definite,indirect,possible \ --suppressions=/path/to/lammps/tools/valgrind/FlexiBLAS.supp \ --suppressions=/path/to/lammps/tools/valgrind/GTest.supp \ --suppressions=/path/to/lammps/tools/valgrind/Kokkos.supp \ @@ -21,7 +22,7 @@ valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \ Or you can create a file $HOME/.valgrindrc with one option per line: --leak-check=full ---show-leak-kinds=all +--show-leak-kinds=definite,indirect,possible --track-origins=yes --suppressions=/path/to/lammps/tools/valgrind/FlexiBLAS.supp --suppressions=/path/to/lammps/tools/valgrind/GTest.supp @@ -37,4 +38,4 @@ Or you can create a file $HOME/.valgrindrc with one option per line: These options will be automatically added to the valgrind command line, so it becomes: valgrind lmp -in in.melt -Last update: 2026-06-27 +Last update: 2026-07-26 diff --git a/unittest/cplusplus/test_advanced_utils.cpp b/unittest/cplusplus/test_advanced_utils.cpp index beab937ff16..1a595201fa9 100644 --- a/unittest/cplusplus/test_advanced_utils.cpp +++ b/unittest/cplusplus/test_advanced_utils.cpp @@ -163,6 +163,9 @@ TEST_F(AdvancedUtils, expand_args) args[8] = utils::strdup("c_gofr[*][*]"); // disable use of input->command and input->arg which point to the last run command right now + // must be restored afterwards, or Input cannot free its argument list + char *saved_command = lmp->input->command; + char **saved_arg = lmp->input->arg; lmp->input->command = nullptr; lmp->input->arg = nullptr; @@ -253,6 +256,9 @@ TEST_F(AdvancedUtils, expand_args) for (int i = 0; i < oarg; ++i) delete[] args[i]; delete[] args; + + lmp->input->command = saved_command; + lmp->input->arg = saved_arg; } TEST_F(AdvancedUtils, check_packages_for_style)