ERROR: double free or corruption

Hello!
I am trying to read a tree from a file into some variables, but root keeps crashing and getting mad, and there is no way to solve it.
In particular this is backtrace i get pescatorediLie.txt (9.4 KB).

void MakeChargeHist(const char* fileIN, int CH) {
    int i, Nentries;
    float Integral;
    float BaseIntegral;
    TFile* f;
    TFile *g;
    TTree *t1;
    TTree *tbase;
    TTree *t2;
    TTree* tset;
    WaveForm Wave;
    mySetting st;

    char fileRAWname[STR_LENGTH];
    char histOUT[STR_LENGTH];

    std::strcpy(fileRAWname, appendToRootFilename(fileIN, "RAW").c_str());
    std::strcpy(histOUT, appendToRootFilename(fileIN, "hist").c_str());

    f = TFile::Open(fileRAWname);

    t1 = (TTree*) f->Get("t1");
    tbase = (TTree*) f->Get("tbase");
    tset = (TTree*) f->Get("tset");
 

    mySetting_get(tset, &st);
}

Macro crashes when at mySetting_get function:

void mySetting_get(TTree* tset1, mySetting* st) {
    tset1->SetBranchAddress("PMT_ID", &st->PmtID);
    tset1->SetBranchAddress("Voltage", &st->voltage);
    tset1->SetBranchAddress("threshold", &st->thresh);
    tset1->SetBranchAddress("Delay_ns", &st->delayns);
    tset1->SetBranchAddress("Date", st->date);
    tset1->GetEntry(0);
}

This is the definition of the structure mySetting

typedef struct {
    char date[STR_LENGTH];
    float voltage;
    int PmtID;
    float thresh;
    int delayns;
    //Aggiungere altri parametri rilevanti come deltaT, descrizione ...

} mySetting;

What’s wrong with me?

    TFile* f;
......
    TTree* tset;
......
    mySetting st;
......
    mySetting_get(tset, &st); // calling SetBranchAddress.
}

means that at the end the routine the TTree still hold reference to the stack variable ‘st’ after the end of the function.
If setting the address to a transient/stack object, call ResetBranchAddresses() before the end of the lifetime of the object.

This may or many not be the cause of the problem.

To track is down, I recommend:

  • update the script to make compilable (adding #include)
  • run the example using ACliC to compile the script.
  • run the ACLiC failing example with valgrind
valgrind --suppressions=$ROOTSYS/etc/valgrind-root.supp root.exe -b -l -q pescatorediLie.C+

Hi thanks for your reply.
Unluckily it does not work. I still get that error. By the way I never delete that tree

Did you follow the other steps that Philippe suggested?

no way, just logs and logs

Thank you for your replies. I still cannot solve the problem. I attach here the VALGRIND logs: pescatorediValgrind.txt (12.8 KB)
ResetBranchAddresses() does not change anything.

Try with a ROOT generated “analysis skeleton”.

I found the cause of the problem. Root is not understanding a typedef struct.
If i use

struct mySetting {
    char date[STR_LENGTH];
    float voltage;
    int PmtID;
    float thresh;
    int delayns;
    //Aggiungere altri parametri rilevanti come deltaT, descrizione ...

} ;

instead of

typedef struct {
    char date[STR_LENGTH];
    float voltage;
    int PmtID;
    float thresh;
    int delayns;
    //Aggiungere altri parametri rilevanti come deltaT, descrizione ...

} mySetting;

root won’t crash. Why the hell is that??

Hard to tell. Whenever strange things are happening in C++ code, the probability is high that you have introduced undefined behavior somewhere in your code (in parts of your code that you haven’t posted).

The difference between (a) typedef struct { ... } mySetting; and (b) struct mySetting { ... }; is that (a) defines an anonymous struct and makes “mySetting” an alias to that struct while (b) simply defines the struct “mySetting”. With (a) you cannot forward declare the struct.

Example:

struct Foo; typedef struct { int a = 42; } Foo; Foo foo; // (a) doesn't compile
struct Foo; struct Foo { int a = 42; }; Foo foo; // (b) compiles

There might be other subtle differences.

You don’t need typedef at all in C++. Use using alias_name = whatever_type; instead if you need to define an alias, most common use case is probably a templated container type where one would define the alias “using value_type = T”.

Back to your problem: from what I see in the logs, your code didn’t even compile.

a) permission denied (why is that?):
Info in TUnixSystem::ACLiC: creating shared library /home/sfera/Desktop/jupiter/src/./ChargeHist_cpp.so
sh: /home/sfera/Desktop/jupiter/src/ChargeHist_cpp.d: Permission denied

b) /home/sfera/Desktop/jupiter/src/./ChargeHist.cpp:64:5: error: ‘strcpy’ is not a member of ‘std’
std::strcpy(fileRAWname, appendToRootFilename(fileIN, “RAW”).c_str());

Did you include <cstring>? strcpy is dangerous, strlcpy is the better function.
On the other hand: is there any reason at all to use use a char array for the file&histogram names? Simply use std::string or TString! By the way: it seems you are using the same STR_LENGTH for both the string from the root input file and your filename strings.

c) you get a couple of warnings because of singned/unsigned comparisons. You should fix all warnings.

Please follow pcanal’s track down list (first reply).