Error: redefinition of a variable

When I try to load the same code a second time in the terminal, it shows the following error.

My understanding is that if you create a variable using “new”, the memory is stored in a heap so you have to use delete command to free the space. However, I have defined the variable normally so it should be stored in stack memory and should be freed after the program ends.

How can I execute my code without getting the following error? Thank you.

Hi,
this was a limitation of the ROOT interpreter until recently (stemming from the fact that C++ does not like redefinition of variables).

In ROOT v6.22 (or maybe already in v6.20) the situation is greatly improved. What ROOT version are you on?

Cheers,
Enrico

My ROOT version is 6.16/00.

Yep,
so that’s it. Please check https://root.cern/install for available ways to upgrade to a more recent ROOT version.

Cheers,
Enrico

@eguiraud

I think I have the same issue even though I have the new root installed.

how to avoid getting redefinition error when running multiple macro with ProcessLine command in ROOT? All this macros have same variable definitions and names, but they are independent macros. When we link, I guess ROOT sees them as one. Thus, we get an error of redefinition.

Code:

//https://root.cern.ch/doc/master/classTROOT.html#a7fed7b8f28a6ea5b41bdf5f8ef3cd638
//https://root.cern/manual/root_macros_and_shared_libraries/

#include <iostream>
#include <string>
#include "TString.h"
#include <TROOT.h>

#define SourcePATH "PATH..."


using namespace std;

void maincompilation() {
    // Load and execute macro1.C
    TString fullFilePath1 = TString::Format("%s%s", SourcePATH, "densityplot.cpp");
    TString fullFilePath2 = TString::Format("%s%s", SourcePATH, "STPMediumSi.cpp");
    TString fullFilePath3 = TString::Format("%s%s", SourcePATH, "STPElectronPositron.cpp");
    TString fullFilePath4 = TString::Format("%s%s", SourcePATH, "STPprotonDifferentMediums1.cpp");
    TString fullFilePath5 = TString::Format("%s%s", SourcePATH, "STPprotonDifferentMediums2.cpp");
    TString fullFilePath6 = TString::Format("%s%s", SourcePATH, "STPprotonDifferentMediums3.cpp");

    gROOT->ProcessLine((std::string(".x ") + fullFilePath1.Data()).c_str());
    gROOT->ProcessLine((std::string(".x ") + fullFilePath2.Data()).c_str());
    gROOT->ProcessLine((std::string(".x ") + fullFilePath3.Data()).c_str());
    gROOT->ProcessLine((std::string(".x ") + fullFilePath4.Data()).c_str());
    gROOT->ProcessLine((std::string(".x ") + fullFilePath5.Data()).c_str());
    gROOT->ProcessLine((std::string(".x ") + fullFilePath6.Data()).c_str());


}

It is difficult to see the error you get as we do not have your .cpp files.

This kind of errors on my side: Basically

All this macros have same variable definitions and names, but they are independent macros. When we link, I guess ROOT sees them as one. Thus, we get an error of redefinition.
`

In file included from input_line_58:1:

**/Users/spyhunter0066/Library/CloudStorage/OneDrive-harran.edu.tr/MacbookCplusplus/STOPPINGPOWERROOT/STOPPINGPOWERROOT/STPMediumSi.cpp:64:8:** **error:** **redefinition of 'PATH'**

string PATH ="/Users/spyhunter0066/Library/CloudStorage/OneDrive-harran.edu.tr/MacbookCplusplus/STOPPINGPOWERROOT/STOPPINGPOWERROOT/";

**^**

**/Users/spyhunter0066/Library/CloudStorage/OneDrive-harran.edu.tr/MacbookCplusplus/STOPPINGPOWERROOT/STOPPINGPOWERROOT/densityplot.cpp:55:8: note:** previous definition is here

string PATH ="/Users/spyhunter0066/Library/CloudStorage/OneDrive-harran.edu.tr/MacbookCplusplus/STOPPINGPOWERROOT/STOPPINGPOWERROOT/";

/Users/spyhunter0066/Library/CloudStorage/OneDrive-harran.edu.tr/MacbookCplusplus/STOPPINGPOWERROOT/STOPPINGPOWERROOT/STPprotonDifferentMediums1.cpp:51:17: error: redefinition of 'T_particle1'
vector <double> T_particle1; //take and read the list from an input file
                ^
/Users/spyhunter0066/Library/CloudStorage/OneDrive-harran.edu.tr/MacbookCplusplus/STOPPINGPOWERROOT/STOPPINGPOWERROOT/STPElectronPositron.cpp:49:17: note: previous definition is here
vector <double> T_particle1; //take and read the list from an input file
          
........

[EnergyList1.txt|attachment](upload://oBJ55y6xcGoBIC9I6zuFXBnJQx4.txt) (1.1 KB)
[STPprotonDifferentMediums1.cpp|attachment](upload://9cxpUfgktrxYwiy1J7DyEGVHEvy.cpp) (16.4 KB)
[STPElectronPositron.cpp|attachment](upload://zREIAwFH8ACnMtnrr5lvpk5kJxk.cpp) (13.7 KB)
[maincompilation.cpp|attachment](upload://hIj8Vm16lAQgniuTn90li6aGDbV.cpp) (1.5 KB)

I want to solve it without renaming all the variables.

Cheers in advance.

Ideas for workarounds:

  • Use a bash script to run several ROOT commands, instead of a ROOT script. No need to overcomplicate things.
  • Or use a namespace for the global variables on the top of your script.
  • Or do not use global variables, rather everything within named macro scope and passing by argument to function.
  • Or you could also ‘unload the script’ before loading the next one. Take a look at the .U command. (write .? in the terminal to see the help).

Thanks for the suggestions.

These lines worked.

gROOT->ProcessLine((std::string(“.x “) + fullFilePath3.Data()).c_str());
gSystem->Unload(fullFilePath3.Data().c_str());
gROOT->LoadMacro(”…cpp”);
gROOT->Reset();
gROOT->ProcessLine(…);

Yes, .U exists in ROOT. Open ROOT, and type .? to see the help.

You probably don’t need LoadMacro and Reset. Just ProcessLine and Unload.

gROOT->ProcessLine((std::string(".x ") + fullFilePath3.Data()).c_str());
gROOT->ProcessLine((std::string(".U ") + fullFilePath3.Data()).c_str());
gROOT->ProcessLine((std::string(".x ") + fullFilePath4.Data()).c_str());

WORKED for 2 macros if I write like above! When I add .U for the second or more macros, I got this error.

Code line:

gROOT->ProcessLine((std::string(".x ") + fullFilePath1.Data()).c_str());
gROOT->ProcessLine((std::string(".U ") + fullFilePath1.Data()).c_str());
gROOT->ProcessLine((std::string(".x ") + fullFilePath2.Data()).c_str());
gROOT->ProcessLine((std::string(".U ") + fullFilePath2.Data()).c_str());
...

Error:

root.exe(1766,0x1dff75000) malloc: double free for ptr 0x13c9cc400
root.exe(1766,0x1dff75000) malloc: *** set a breakpoint in malloc_error_break to debug

I then really recommend using bash, or moving the global variables to local ones.

You can also report the error here if you want Sign in to GitHub · GitHub

Or simply using:

root -l -b -q yourmacro1.c
root -l -b -q yourmacro2.c
root -l -b -q yourmacro3.c

in the system terminal. You can also pass arguments to the function:

root -l -b -q yourmacro1.c+(\"abc.txt\")

For bash, is this enough.

#!/bin/bash

root -l
echo “Running Macro 1…”

.x /PATH…/densityplot.cpp

echo “Running Macro 2…”

.x /PATH…/STPMediumSi.cpp

Add more macros as needed


Then, I wrote on a terminal:
./run_macros.sh

// chmod +x *.cpp
//chmod +x run_macros.sh

I got these errors.

…densityplot.cpp: Permission denied
…STPMediumSi.cpp: Permission denied

Some suggests ```
g++ -o executable_name filename.cpp

Replace executable_name with the desired name of the executable binary, and filename.cpp with the name of your C++ source file.

However, g++ compiler doesn’t accept ROOT header files to compile in that way.

HOW TO RUN A BASH CODE with direct root macro?

Nope.

Use the following:

#!/bin/bash

yourPath="./myfolder"
root -l -b -q ${yourPath}/yourmacro1.c
root -l -b -q ${yourPath}/yourmacro2.c

For some reason, it opens up XQuarts instead of ROOT to visualize. XQuarts opens empty canvas by the way. How can we make it open ROOT.
Plus, should we use -q because I want to see all plots at once on my screen.
THANKS. Sorry for the pain. It shouldn’t take that long to solve this.

yes, use -q to close ROOT.

What you need to do is store the result of each macro in a file called for example plots.root

In the first macro .C, you open this new TFile(“plots.root”) in “RECREATE” mode, in the other macros in “UPDATE” mode.

Finally, in your bash script, run:

root -l plots.root -e ‘new TBrowser’

this time without -b -q

and double click on the plots so that they appear on your screen.

I see your point, but that’s not what I wanted. I wanted to compile and see the files one by one indeed.

This code runs but it doesn’t plot anything. what’s wrong with it? I save each macro’s canvas in a root file separately.

#!/bin/bash

yourPath=“PATH/”

Start ROOT session and open the ROOT files within the ROOT interpreter

root -l -b << EOF
{
// Open the ROOT file
TFile *file = TFile::Open(“${yourPath}densityplot.root”);
if (!file) {
std::cerr << “Error: Could not open densityplot.root” << std::endl;
return 1;
}

// Get the canvas named "c1" from the file
TCanvas *c1 = (TCanvas*)file->Get("c1");
if (!c1) {
    std::cerr << "Error: Could not find canvas c1 in densityplot.root" << std::endl;
    return 1;
}

// Draw the canvas
c1->Draw();

}
EOF

root -l -b << EOF
{
// Open the ROOT file
TFile *file = TFile::Open(“${yourPath}STPElectronPositron.root”);
if (!file) {
std::cerr << “Error: Could not open STPElectronPositron.root” << std::endl;
return 1;
}

// Get the canvas named "c3" from the file
TCanvas *c3 = (TCanvas*)file->Get("c3");
if (!c3) {
    std::cerr << "Error: Could not find canvas c3 in STPElectronPositron.root" << std::endl;
    return 1;
}

// Draw the canvas
c3->Draw();

}
EOF

You need to create a TFile, and write the canvas to the TFile using c->Write();

It worked alright after TFile and write() method.
I use this now. The weird thing is, plots show up only if I select the root file in the Browser and pick up one by one. Should I write the graphs I create instead of Canvas to see in the TBrowser?

#!/bin/bash

yourPath=“…”

root -l -b -q ${yourPath}macro1.cpp

root -l -b -q ${yourPath}macro2.cpp

root -l -b -q ${yourPath}macro3.cpp

root -l -b -q ${yourPath}macro4.cpp

root -l -b -q ${yourPath}macro5.cpp

root -l -b -q ${yourPath}macro6.cpp

#To see all at once
root -l ${yourPath}plots.root -e “new TBrowser”