Getting `illegal pointer` error when using AddFriend from ROOT(cern) - c++

Aim;
I wish to compare the contents of two ROOT TTree objects that have identical structure (but not identical contents obviously). The best way to do this seems to be using AddFriend.
Problem;
I am getting this error message;
Error: illegal pointer to class object t3 0x0 1681 makeFriends.C:6:
*** Interpreter error recovered ***
What I've tried so far;
After running the example at the bottom of this page successfully I decided to reduce it down to just the reading and friend adding section, as I had already created tree3.root and tree3f.root in the first run. So I had a file called tree3.C containing;
// Function to read the two files and add the friend
void tree3r() {
TFile *f = new TFile("tree3.root");
TTree *t3 = (TTree*)f->Get("t3");
// Add the second tree to the first tree as a friend
t3->AddFriend("t3f","tree3f.root");
// Draw pz which is in the first tree and use pt
// in the condition. pt is in the friend tree.
//t3->Draw("pz","pt>5");
}
This worked as expected, when loaded (root[] .L tree3.C) and run (root[] tree3r()) from the root prompt.
So I put a copy in a folder containing both of my root files, plainMaskOutput.root and DNMaskOutput.root, and changed strings in the copy to match the names of my files. So I have;
// Function to read the two files and add the friend
void tree3r() {
TFile *f = new TFile("plainMaskOutput.root");
TTree *t3 = (TTree*)f->Get("t3");
// Add the second tree to the first tree as a friend
t3->AddFriend("t3f","DNMaskOutput.root");
// Draw pz which is in the first tree and use pt
// in the condition. pt is in the friend tree.
//t3->Draw("pz","pt>5");
}
Which gives the error above. I dont understand why these things are behaving diffrently? Why can't they just be friends?

It turned out that TFiles method Get might return null, indicating the failure. You were not taking that into account. Why does it return null in your case?
According to the link I provided in the comments (https://root.cern.ch/phpBB3/viewtopic.php?t=12407) it is because your file doesn't contain a tree having a name you provided.
It will be better to add an explicit check of the returned value from Get. if the file gets changed later, your program will start to crash again.

The problem is that plainMaskOutput.root is a file name and the string inside the Get() parenthesis is the tree name. The file called plainMaskOutput.root did not contain a tree by the name t3 it contained one by the name HitsTree. So the line should have been;
TTree *foo = (TTree*)f->Get("HitsTree");
Similarly, the add friend command needed to have the name of the tree stored in DNMaskOutput.root, but as they have the same name it should be aliased;
foo->AddFriend("DNHitsTree = HitsTree","DNMaskOutput.root");
This is just the problem I was having this time, it may not always be the problem associated with this error. I am not knowledgeable enough in this area to say what other problems are possible.

Related

ROOT - pyroot: Branch seen as leaf, can't access actual leaves

I am trying to extract information from a root file using pyroot.
I tried using the usual GetBranch, GetLeaf, GetValue but it does not work as usual, so I tried alternatives.
I found an equivalent code in c++ which is extracting the values just fine from my ROOT file but when applying the same thing in pyroot, I get an empty object as my "mcinfo" (see below).
I also tried displaying the branches and leaves with GetListOfBranches() and GetListOfLeaves(). I get the proper list of branches with the first but when looking at the list of leaves (here MC but it's the same with all branches), I get out of MC.GetListOfLeaves() that the only leaf is MC too... I have several leaves (for instance energy) that I can access just fine with the c++ code and directly with data.Scan("energy") too...
Anyone has an idea of how to fix this? Sorry, I am not that familiar with ROOT yet. I assume it is a rather easy fix, but I don't see what is wrong with this...
C++ code:
TFile *file = new TFile(fname);
TTree *data = (TTree*)file->Get("data");
TBranch * McinfoBranch;
MCInfo* mcinfo = (MCInfo*)file->GetList()->FindObject("MC");
data->SetBranchAddress("MC", &mcinfo, &McinfoBranch);
pyroot version:
infile = ROOT.TFile(fname)
data = infile.Get("data")
mcinfo = infile.GetList().FindObject("MC")
which gives me this when printing mcinfo: <cppyy.gbl.TObject object at 0x(nil)>.

python win32com shell.SHFileOperation - any way to get the files that were actually deleted?

In the code I maintain I run across:
from win32com.shell import shell, shellcon
# ...
result,nAborted,mapping = shell.SHFileOperation(
(parent,operation,source,target,flags,None,None))
In Python27\Lib\site-packages\win32comext\shell\ (note win32comext) I just have a shell.pyd binary.
What is the return value of shell.SHFileOperation for a deletion (operation=FO_DELETE in the call above) ? Where is the code for the shell.pyd ?
Can I get the list of files actually deleted from this return value or do I have to manually check afterwards ?
EDIT: accepted answer answers Q1 - having a look at the source of pywin32-219\com\win32comext\shell\src\shell.cpp I see that static PyObject *PySHFileOperation() delegates to SHFileOperation which does not seem to return any info on which files failed to be deleted - so I guess answer to Q2 is "no".
ActiveState Python help contains SHFileOperation description:
shell.SHFileOperation
int, int = SHFileOperation(operation)
Copies, moves, renames, or deletes a file system object.
Parameters
operation : SHFILEOPSTRUCT
Defines the operation to perform.
Return Value
The result is a tuple containing int result of the
function itself, and the result of the fAnyOperationsAborted member
after the operation. If Flags contains FOF_WANTMAPPINGHANDLE, returned
tuple will have a 3rd member containing a sequence of 2-tuples with
the old and new file names of renamed files. This will only have any
content if FOF_RENAMEONCOLLISION was specified, and some filename
conflicts actually occurred.
Source code can be downloaded here: http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/ (pywin32-219.zip)
Just unpack and go to .\pywin32-219\com\win32comext\shell\src\

when to call _findclose?

Note: Since problem is solved, I've added comments to my original posts.
According to "http://msdn.microsoft.com/en-us/library/6tkkkc1y%28v=vs.90%29.aspx", it stated as this:
*You must call _findclose after you are finished using either the _findfirst or _findnext function (or any variants). This frees up resources used by these functions in your application.*
--comment: it is vague, but what microsoft is trying to say is: some users just need to find the first file(they don't need to call _findnext), then call _findclose; some users called _findnext (they MUST have already called _findfirst), after finished using that, call _findclose. Actually _findnext can be called multiple times, while _findclose is only responsible to a handle, which is created by _findfirst.
And following is a piece of code that is widely used to list files in the directory. -- comment: it is correct.
For example, if there are 2 files and 1 directory in the directory, then:
.
..
ddd
file1.txt
file2.txt
_findfirst is called once. the handle's corresponding fileinfo is system directory "." (is that right?)
--comment: no. the handle is a group of files+directories, the fileinfo is acting as the "cursor". (fileinfo always contained the "name" field, I bet the implementation of _findnext is using the "name" to find the next in a group of files+directories specified by the handle)
_findnext is called 4 times. (the first argument is always the handle corresponding to ".", is that right?)
--comment: yes + no. The first argument is always the same handle; the handle is NOT corresponding to any fileinfo, but to a group of them.
My questions are:
Does "_findclose" be called ONCE is enough?
*--comment:* yes.
if _findnext will not change the handle value, how can it "remember" where to start to find the next file(or directory)? (sorry, maybe I was thinking in the "linked list" pattern.)
*--comment:* I bet is using fileinfo's name field. Just as in Windows Explorer, we sort the contents in a folder, given a file name, we can know their position in the list, so we can "find next".
Are there any harm to call _findclose more times than needed? (like crash or something)
*--comment:* a stupid question. Sorry!
Or is the following code wrong at all? If yes, what's the correct way to implement it?
--It is correct code.
// List the files in the directory
intptr_t file;
_finddata_t filedata;
file = _findfirst(desc.c_str(),&filedata);
if (file != -1)
{
do
{
cout << filedata.name << endl;
// Or put the file name in a vector here
} while (_findnext(file,&filedata) == 0);
}
else
{
cout << "No described files found" << endl;
}
_findclose(file);
I asked this because I've met an issue that an application is freezing a directory which can not be deleted if the process is alive. However, I can guaranteed that "_findclose" is called on every return value from "_findfirst". If I add "_findclose" after calling "_findnext", then will fix the issue perfectly. How can you help me to explain it?
--comment: pardon. don't use "guarantee" too easy. That's where the bug is.
Note: I don't have problem to understand what is a handle, like open a file, read/write/read/write..., close the file handle. I just find the documentations describing these three APIs are vague.
--comment: go to improve your english.
Thank you in advance.
Your calls to _findclose should match with your calls to _findfirst -- i.e., each time you call _findfirst, you should have a matching call to _findclose.
In the code above, since you have only one call to _findfirst, it's correct to have only one call to _findclose.
If you were doing a recursive search of subdirectories, then you'd end up with multiple calls to _findfirst as you descend the hierarchy, and matching calls to _findclose as you finish and ascend back up the hierarchy.
You only need to call _findclose once, when you are finished.
On Windows, a directory may be locked if it is the current directory of your process. Try calling _chdir.
If that doesn't work... are you opening any of the files in the directory you're searching? An open file may lock the directory as well.
It may be useful to let Process Explorer get a look at your app. It can tell you for sure what handle you have left open.

Create/Initialize new object using variables

I am intending to initialize or create a new object using variables.
The error says that i am conflicting declaration.
//instantiate new node object***********************
string peer = "peer";
string pNo = convertInt(addPeerNum); //convert peer number to string to concatenate 2 strings
string NewPeerObject = peer+pNo; << ERROR POINTS TO HERE
nodes NewPeerObject; << ERROR POINTS TO HERE
Error message:
conflicting declaration 'nodes NewPeerObject' <-- last line of error
'NewPeerObject' has a previous declaration as 'string NewPeerObject' <-- 2nd last line
My main point is to create a new object when I add more peers.
If I addpeer 1, it will create a new object 'peer1'
If I addpeer 2, it will be 'peer2' etc.
I am reading in the file which contains
addpeer 1
addpeer 100
addpeer 28
In my program, it reads the file and stores the number in a variable called 'addPeerNum'
and with me doing this, it actually has a different string content of 'NewPeerObject'.
So in this instance, i am actually trying to create 3 new objects.
Is there any way which i will be able to do it?
You cannot have two objects with same name like that. It violates the One definition Rule, naturally the compiler complains.
Just please do yourself a favor and change the name of either of them.
I think that what you are looking for is a kind of dynamically resized array of your objects.
You can use std::list to achieve that kind of behavior.
std::list<PeerObject> list;
PeerObject peer(peer_string);
list.insert(peer);
or a std::map if you want to use your peer string as a key
std::map<std::string, PeerObject> peer_map;
PeerObject peer(peer_string);
peer_map.insert(peer_string, peer);
// .... add more
PeerObject& foundObj = peer_map[a_key];
foundObj.doSomething();
You could also do it with MACROs but only at compile time and you should avoid them if possible.

binary tree doesn't rebuild from file

I'm new on data structures and we were assigned to make a guessing game using binary tree implementation. I have accomplished the program flow without file implementation. I have saved the binary tree preorderly on an external file now I have problem in rebuilding tree from file
in my file I have:
Is it Angel Locsin?:#Neneng B?Is it Sam Pinto? ##White Beauty?Is it
Marian Rivera? ##HotandSexy?Is it Cristine Reyes? ###
The "#" is for a NULL node.
I have also my code. I follow the algorithm of what my professor gave me. I searched on the internet and gave me same algorithm as of what my prof said. My problem is on every third non-null data the program crashes. I think the main reason of crashing is a node that was not set to null after the third non-null data is inserted. If so, how could I set it to NULL so that my program will not crash.I assigned the data from file into array of strings and set a "\0" at the last index of array.
void read(node *temp)
{
while(array[j]=="#")
j++;
if(array[j]=="\0")
return;
node *nNode;
nNode = new node;
nNode->yes=NULL;
nNode->no=NULL;
nNode->data=array[j];
j++;
temp=nNode;
read(temp->yes);
read(temp->no);
}
Your problem is in the definition of your read function. I guess the idea is that "temp" is an output parameter of type "node*". But this is not what you have written.
You need to have a pointer or a reference to the "node*" parameter like e.g. so:
void read(node** temp)
Then adjust the rest of the code such that is compiles by proper (de)referencing. This should solve your crash.