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).

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.