Multi-thread: Random in AvalancheMC and AvalancheMicroscopic

Hi,

I’m currently rewriting my code to enable multi-threading with OpenMP, following the examples provided. However, I’ve noticed that the results vary depending on the number of threads used to run the code.

I suspect that the random number generation methods, such as Random::RndmUniform, which are used in both AvalancheMC and AvalancheMicroscopic, might not be thread-safe.

Could this be the cause of the issue?

Thanks for your help,

Pierre

Hello, adding @hschindl in the loop

Hello,

Is your Garfield++ installation at least as recent as commit 101dfdae? I just ran the pixel_mt.C example and obtained the same results for both sequential and parallel execution.

Sincerely,
Gabriel

Hi,

indeed, after fixing the issue reported by @gabrielribcesario, AvalancheMCshould be thread-safe now. However, even if you fix the seed of the random number generator, you will not get identical results every time you run the program in the parallelized version of the code.

Hi @gabrielribcesario and @hschindl , thank you for this detail !

Nevertheless, even after pulling last commit, I still have issues when launching my code with OMP_NUM_THREADS > 1. Errors like these occur.

AskedDensity_mt(87454,0x1f74960c0) malloc: *** error for object 0x600001c37ca0: pointer being freed was not allocated
AskedDensity_mt(87454,0x1f74960c0) malloc: *** set a breakpoint in malloc_error_break to debug

 *** Break *** segmentation violation

 *** Break *** segmentation violation

 *** Break *** segmentation violation
[1]    87454 abort      OMP_NUM_THREADS=7 ./AskedDensity_mt --density 9e10

Here is the OpenMP-parallelized part of my code; the full code is in the attached file. I am trying to drift e-, i+, and i- in parallel, but unlike the example, I want to drift them step by step in time in order to update some density maps.

Thanks for your help.

  // -- Simulation -- //
  // Create buffers
  const int T = omp_get_max_threads();
  std::vector<std::vector<P>> electrons_b(T);
  std::vector<std::vector<P>> ions_b(T);
  std::vector<std::vector<P>> negions_b(T);

  double t = tStartSimu;
  while (t < tEndSimu) {
    for (int k=0;k<T;++k) {
      electrons_b[k].clear();
      ions_b[k].clear();
      negions_b[k].clear();
    }
      
    // --- Drift e- ------------------------------------------------------
    const int nelectrons = electrons.size();
    #pragma omp parallel
    {
      const int tid = omp_get_thread_num();
      #pragma omp for reduction(+: nAttaElectrons)
      for (int i = 0; i < nelectrons; ++i) {
        AvalancheMicroscopic aval;
        aval.SetSensor(&sensor);
        aval.SetTimeWindow(t, t+dt);
        aval.DriftElectron(electrons[i].x, electrons[i].y, electrons[i].z,
                           electrons[i].t, 0.1, 0., 0., 0., electrons[i].w);
        for (const auto& p : aval.GetElectrons()) {
          const auto& p1 = p.path.back();
          if (p.status == -7) {
            nAttaElectrons++;
            negions_b[tid].push_back(P{p1.x, p1.y, p1.z, p1.t, p.weight});
          }
          else electrons_b[tid].push_back(P{p1.x, p1.y, p1.z, p1.t, p.weight});
        }
      }
    }

    for (auto& b : negions_b) {
      negions.insert(negions.end(), b.begin(), b.end());
    }
    for (auto& k : negions_b) k.clear();

    // --- Drift i- ------------------------------------------------------
    const int nnegions = negions.size();
    #pragma omp parallel
    {
      const int tid = omp_get_thread_num();
      #pragma omp for reduction(+: nRecombNegions)
      for (int i = 0; i < nnegions; ++i) {
        AvalancheMC driftnegion;
        driftnegion.SetSensor(&sensor);
        driftnegion.EnableRecombination(withIonRecombination, alpha);
        driftnegion.EnableDiffusion(withIonDiffusion);
        driftnegion.EnableDensityMap(withDensityMap);
        driftnegion.SetTimeSteps(.2); // [ns] default 0.02
        driftnegion.SetTimeWindow(t, t+dt);
        driftnegion.DriftNegativeIon(negions[i].x, negions[i].y, negions[i].z,
                                     negions[i].t, negions[i].w);
        for (const auto& p : driftnegion.GetNegativeIons()) {
          const auto& p1 = p.path.back();
          if (p.status == -9) nRecombNegions++; 
          else negions_b[tid].push_back(P{p1.x, p1.y, p1.z, p1.t, p.weight});
        }
      }
    }

    // --- Drift i+ ------------------------------------------------------
    const int nions = ions.size();
    #pragma omp parallel
    {
      const int tid = omp_get_thread_num();
      #pragma omp for reduction(+: nRecombIons)
      for (int i = 0; i < nions; ++i) {
        AvalancheMC driftion;
        driftion.SetSensor(&sensor);
        driftion.EnableRecombination(withIonRecombination, alpha);
        driftion.EnableDiffusion(withIonDiffusion);
        driftion.EnableDensityMap(withDensityMap);
        driftion.SetTimeSteps(.2); // [ns] default 0.02
        driftion.SetTimeWindow(t, t+dt);
        driftion.DriftIon(ions[i].x, ions[i].y, ions[i].z,
                          ions[i].t, ions[i].w);
        for (const auto& p : driftion.GetIons()) {
          const auto& p1 = p.path.back();
          if (p.status == -9) nRecombIons++;
          else ions_b[tid].push_back(P{p1.x, p1.y, p1.z, p1.t, p.weight});
        }
      }
    }
    
    // --- Update global variable and clear buffers -----------------------
    electrons.clear();
    for (auto& b : electrons_b) {
      electrons.insert(electrons.end(), b.begin(), b.end());
    }
    negions.clear();
    for (auto& b : negions_b) {
      negions.insert(negions.end(), b.begin(), b.end());
    }
    ions.clear();
    for (auto& b : ions_b) {
      ions.insert(ions.end(), b.begin(), b.end());
    }

    grid.ClearFields();
    grid.SetUniformElectricField(0., 0., 0.);
    for (auto& ion : ions) grid.AddIon(ion.x, ion.y, ion.z, ion.w);
    for (auto& nion : negions) grid.AddNegativeIon(nion.x, nion.y, nion.z, nion.w);

    t += dt;
  }

AskedDensity_mt.cc (10.9 KB)

Edit: I just ran the code with OMP_NUM_THREADS=4 and it suddenly worked without changing anything. Then I ran it again and got this error. It seems very unstable — the more I increase the number of threads or the number of simulated pairs, the more likely it fails.

 *** Break *** segmentation violation
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<double, std::__1::allocator<double>>::vector(std::__1::vector<double, std::__1::allocator<double>> const&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<double, std::__1::allocator<double>>::vector(std::__1::vector<double, std::__1::allocator<double>> const&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] void std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>::construct[abi:ne190102]<std::__1::vector<double, std::__1::allocator<double>>, std::__1::vector<double, std::__1::allocator<double>>&>(std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] void std::__1::allocator_traits<std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::construct[abi:ne190102]<std::__1::vector<double, std::__1::allocator<double>>, std::__1::vector<double, std::__1::allocator<double>>&, 0>(std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>&, std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<double, std::__1::allocator<double>>* std::__1::__uninitialized_allocator_copy_impl[abi:ne190102]<std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>, std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*>(std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>&, std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<double, std::__1::allocator<double>>* std::__1::__uninitialized_allocator_copy[abi:ne190102]<std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>, std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*>(std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>&, std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] void std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::__construct_at_end<std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*>(std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*, unsigned long) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] void std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::__init_with_size[abi:ne190102]<std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*>(std::__1::vector<double, std::__1::allocator<double>>*, std::__1::vector<double, std::__1::allocator<double>>*, unsigned long) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::vector(std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>> const&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::vector(std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>> const&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] void std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>::construct[abi:ne190102]<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>> const&>(std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>*, std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>> const&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] void std::__1::allocator_traits<std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>::construct[abi:ne190102]<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>> const&, 0>(std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>&, std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>*, std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>> const&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>::__construct_at_end(unsigned long, std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>> const&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>::assign(unsigned long, std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>> const&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] Garfield::Medium::Init(unsigned long, unsigned long, unsigned long, std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>&, double) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] Garfield::Medium::VelocityFromMobility(std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>> const&, std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] Garfield::Medium::IonVelocity(double, double, double, double, double, double, double&, double&, double&) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] Garfield::AvalancheMC::GetVelocity(Garfield::Particle, Garfield::Medium*, std::__1::array<double, 3ul> const&, std::__1::array<double, 3ul> const&, std::__1::array<double, 3ul> const&, std::__1::array<double, 3ul>&) const (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] Garfield::AvalancheMC::DriftLine(Garfield::AvalancheMC::Seed const&, std::__1::vector<Garfield::AvalancheMC::Point, std::__1::allocator<Garfield::AvalancheMC::Point>>&, std::__1::vector<Garfield::AvalancheMC::Seed, std::__1::allocator<Garfield::AvalancheMC::Seed>>&, bool, bool) const (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] Garfield::AvalancheMC::TransportParticles(std::__1::vector<Garfield::AvalancheMC::Seed, std::__1::allocator<Garfield::AvalancheMC::Seed>>&, bool, bool, bool) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] Garfield::AvalancheMC::DriftIon(double, double, double, double, unsigned long) (no debug info)
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/AskedDensity_mt] main.omp_outlined.22 (no debug info)
[/opt/homebrew/Cellar/llvm/21.1.0/lib/libomp.dylib] __kmp_invoke_microtask (no debug info)
[<unknown binary>] (no debug info)
AskedDensity_mt(89270,0x38380b000) malloc: double free for ptr 0x14e019200
AskedDensity_mt(89270,0x38380b000) malloc: *** set a breakpoint in malloc_error_break to debug
[1]    89270 abort      OMP_NUM_THREADS=4 ./AskedDensity_mt --density 9e10 --pairs 1e3

Hello,

Can you replace your Medium.cc and Medium.hh with the following files and see if the error persists?

Medium.cc (53.2 KB)
Medium.hh (37.5 KB)

I simply added a mutex right before the tab.assign() command in both overloads of Medium::Init. I’m not sure if this is the most elegant solution, but it did work for me.

Also, for some reason, the crash only occurs if you run both AvalancheMicroscopic and AvalancheMC, or at least it does so for me in the program you’ve attached.

Hi @gabrielribcesario,

Thank you for this, it’s working for me as well now! I also found out while debugging that the issue comes from the combination of AvalancheMC and AvalancheMicroscopic, strange…

Also, in my multi-threaded program, I need to end it with app.Run() in order to prevent the following error. However, when I do this, the program keeps running as if a canvas were open, which is normal. For my sequential code, I don’t need app.Run(), and the program terminates correctly. Could this be related? The error still persists even with the new Medium class.


 *** Break *** bus error
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::default_delete<TStyle>::operator()[abi:ne190102](TStyle*) const (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::unique_ptr<TStyle, std::__1::default_delete<TStyle>>::reset[abi:ne190102](TStyle*) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::unique_ptr<TStyle, std::__1::default_delete<TStyle>>::~unique_ptr[abi:ne190102]() (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::unique_ptr<TStyle, std::__1::default_delete<TStyle>>::~unique_ptr[abi:ne190102]() (no debug info)
[/usr/lib/system/libsystem_c.dylib] __cxa_finalize_ranges (no debug info)
[/usr/lib/system/libsystem_c.dylib] exit (no debug info)
[/usr/lib/system/libdyld.dylib] dyld4::LibSystemHelpers::getenv(char const*) const (no debug info)
[/usr/lib/dyld] dyld4::LibSystemHelpersWrapper::exit(int) const (no debug info)
[/usr/lib/dyld] start (no debug info)

@hschindl , do you think this could be a good bug correction ?

That is likely related to the behavior I’m describing here. Basically, the PlottingEngine class sets a global plotting style with m_style, potentially before the main function initialization since m_style is a static member. In doing so, the ROOT environment gains ownership of the memory address pointed by m_style. During the program shutdown, the ROOT environment frees the memory address before the unique_ptr destructor’s is called, leading to a double-free error.

Thank you for the explanation. It’s a bit too deep for me to understand everything. Is there an easy way to prevent that and shut down the program safely?

Hello,

@hschindl said he would take a look into this. While an official fix is not out yet, I guess you can try adding this to PlottingEngine.cc:

// m_style->cd() and force the style on all existing objects
void PlottingEngine::Initialise() {
  gROOT->SetStyle(m_style->GetName()); 
  gROOT->ForceStyle();
}

// Automatically released by ROOT at the end of the program
// If not, then the memory is reclaimed by the OS (I guess?)
TStyle *PlottingEngine::m_style = new TStyle("Garfield","Garfield Style"); 

// Run PlottingEngine::Initialise() once during program startup
// The constructor wrapper forces static initialization
struct PEInitHelper {
  PEInitHelper() {
    PlottingEngine::Initialise();
  }
};
static PEInitHelper init;

And in PlottingEngine.hh replace the m_style declaration with

  static TStyle *m_style;

and add the following function declaration to the public members of the class:

static void Initialise();

I don’t really like this fix since it relies on either ROOT or the OS to do memory management, plus it might trigger false positives if you’re using a debugger. Other than that, I don’t think it will have any noticeable negative impacts.

By the way, I forgot to comment on this in my previous post. I believe that the real problem lies between AvalancheMC and AvalancheMicroscopic. After all, you’ll only get the problematic behavior if you use both methods, so I’m guessing that the class Medium just so happened to be the one causing the crashes since it is thread-unsafe. @hschindl or one of the other Garfield devs might have some insight on this. Funnily enough, if you run AvalancheMC before AvalancheMicroscopic, you get choppy CPU performance during the AvalancheMicroscopic run and the program takes forever to finish.

It looks like merge request !526 has fixed both problems, the Medium and the PlottingEngine classes, great news !

Edit: I was a bit optimistic about the segmentation violation. I still get errors on some runs, but much less frequently.

 *** Break *** segmentation violation
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::vector<double, std::__1::allocator<double>>::~vector[abi:ne190102]() /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:541
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::vector<double, std::__1::allocator<double>>::~vector[abi:ne190102]() /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:541
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::vector<double, std::__1::allocator<double>>::~vector[abi:ne190102]() /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:541
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>::destroy[abi:ne190102](std::__1::vector<double, std::__1::allocator<double>>*) /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocator.h:168
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] void std::__1::allocator_traits<std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::destroy[abi:ne190102]<std::__1::vector<double, std::__1::allocator<double>>, 0>(std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>&, std::__1::vector<double, std::__1::allocator<double>>*) /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocator_traits.h:336
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::__base_destruct_at_end[abi:ne190102](std::__1::vector<double, std::__1::allocator<double>>*) /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:985
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::__clear[abi:ne190102]() /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:980
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::__destroy_vector::operator()[abi:ne190102]() /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:530
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::~vector[abi:ne190102]() /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:541
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>::~vector[abi:ne190102]() /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:541
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>::destroy[abi:ne190102](std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>*) /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocator.h:168
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] void std::__1::allocator_traits<std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>::destroy[abi:ne190102]<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, 0>(std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>&, std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>*) /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocator_traits.h:336
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>::__base_destruct_at_end[abi:ne190102](std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>*) (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>::__clear[abi:ne190102]() (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>::__destroy_vector::operator()[abi:ne190102]() (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>::~vector[abi:ne190102]() (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] std::__1::vector<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>, std::__1::allocator<std::__1::vector<std::__1::vector<double, std::__1::allocator<double>>, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double>>>>>>::~vector[abi:ne190102]() (no debug info)
[/Users/pierregerard/Applications/garfieldpp/install/lib/libGarfield.0.3.dylib] Garfield::Medium::~Medium() (no debug info)
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] Garfield::MediumGas::~MediumGas() /Users/pierregerard/Applications/garfieldpp/install/include/Garfield/MediumGas.hh:20
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] Garfield::MediumMagboltz::~MediumMagboltz() /Users/pierregerard/Applications/garfieldpp/install/include/Garfield/MediumMagboltz.hh:30
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] Garfield::MediumMagboltz::~MediumMagboltz() /Users/pierregerard/Applications/garfieldpp/install/include/Garfield/MediumMagboltz.hh:30
[/Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/build/flic_mt] main /Users/pierregerard/Desktop/Thesis/garfieldpp_projects/TestComponentGrid/flic_mt.cc:418
[/usr/lib/dyld] start (no debug info)

1 Like

It looks like a problem in MediumMagboltz’s destructor. In Garfield’s top level CMakeLists.txt add the following flags to target_compile_options:

target_compile_options(Garfield PRIVATE
  -g3
  -Og
  -fsanitize=address
...
)

And add

target_link_options(Garfield PRIVATE -fsanitize=address)

right after the compile options. Try triggering the crash and send back the stack trace.

I wasn’t able to find any edits to the Medium.cc and Medium.hh files, I believe they only fixed the plotting style problem.