Rooters, I recently started running into many errors when exiting ROOT, of the form: #Fatal in <operator delete>: unreasonable size (1110139808) #aborting... I assumed that this was my problem and tried to hunt it down. Well, I finally did, but it's not just my problem. Here's the problem, as best I can describe it. I have a class that deals with many histograms all at once. This class has a data member fHists which is an array of TH1F allocated with operator new[]: TH1F *fHists; // In class definition fHists = new TH1F[Length()]; // In constructor When an object of this class is destroyed, it correctly calls operator delete[] on fHists to clean up after itself. So far, so good. But, in the streamer, there is code like this: // Read in the length fHists = new TH1F[Length()]; for (int i = 0; i < Length(); ++i) { fHists[i].Streamer(buf); } and, as readers of roottalk will be aware, that Streamer call will put the TH1F into the gDirectory (usually the file/subdirectory being read from). Now comes the gotcha: if you fail to delete an fData (say, you read it in from file and did some interactive work with it), when ROOT shuts down, it will go through its still-open gDirectory and delete all the undeleted objects -- but it will use operator delete, NOT operator delete[]! This in turn causes Root's operator new/delete builtin protections to activate, causing the fatal error. This is even more of a big deal because it doesn't only happen when shutting down root -- you can trigger it also by doing a Close() on the TFile. At the moment, I can see two potential solutions, both of which have drawbacks, but from which I am probably going to select. 1) Protect the TH1F's from being put in the directory by setting gDirectory to 0. My interactive users don't like this option, because they like the convenience of being able to specify some from this arry of histograms by name, and will probably in at least some cases pull the histograms explicitly into a TDirectory, which causes more problems. 2) Add the object containing the TH1F's also to the gDirectory (ahead of its members) so that it gets cleaned up before its members, since it knows how to clean them up correctly. This doesn't completely solve the problem either, since I need to know all the implementation details of TH1F in order to know all the places where I will have to add/remove this object from a Directory in order to protect its members. And, it's still possible for users to circumvent this protection when the top-level object isn't (yet) in the directory. The best solution, of course, would be for the Root team to either: a) decide that TDirectorys should not own (and therefore delete) their contents, since it is just too easy to Add an object to a directory, then delete it and forget to Remove it. I don't see a huge problem with this solution, but it is a potentially significant change deep in the guts of ROOT... b) make it possible for TDirectories to tell the difference between new and new[]'d objects added to the directory, and not delete the latter (or delete only the zeroth element in the array). c) supply functionality for 'all of an array' of TObject things to be pulled into a TDirectory which will then do the delete[] correctly, in which case I can put protective code around the readin and explicitly put the array into gDirectory myself. George Heintzelman gah@bnl.gov
This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:31 MET