ROOT 2.22.10: auto_ptr test results

From: Matthew D. Langston (langston@SLAC.stanford.edu)
Date: Mon Aug 16 1999 - 01:22:32 MEST


I recently did some experiments which tested how well the "auto_ptr"
class template works with a current version of ROOT.  The purpose of
this e-mail is to briefly post my results.

My results are that, as of ROOT version 2.22.10 (the most current
version of ROOT as I write this), "auto_ptr" can be used interactively
with cint in a limited way with a few caveats:

  1) Only one of the two forms of calling the "auto_ptr" constructor
     works:

       auto_ptr<Foo> foo( new Foo() );  // OK
       auto_ptr<Foo> foo = new Foo();   // broken
     
  2) "operator->" does not work.

Therefore, as long as you stick to "operator*" for accessing your heap
based objects, "auto_ptr" should work well for you.  However, not having
"operator->" doesn't make the "auto_ptr" smart pointer very smart.
Perhaps the constructor and "operator->" problem are fixable in a
straight forward way for Masaharu.

Therefore, instead of using an "auto_ptr" like this:

   auto_ptr<Foo> foo( new Foo() );
   foo->Print();

You will have to use it like this:

   auto_ptr<Foo> foo( new Foo() );
   (*foo).Print();

or this:

   auto_ptr<Foo> foo0( new Foo() );
   Foo& foo1 = *foo0;
   foo1.Print();

Finally, those parts of "auto_ptr" that do work also work well from both
interpreted and compiled code.

The full package which demonstrates the use of "auto_ptr" with ROOT is
available at

ftp://ftp.slac.stanford.edu/users/langston/root/root-auto_ptr-0.01.tar.gz.

I have also attached the README from this package to this e-mail, which
describes the problems in a bit more detail.

--
Matthew D. Langston
SLD, Stanford Linear Accelerator Center
langston@SLAC.Stanford.EDU


		       ROOT 2.22.10 and auto_ptr
		       *************************

                              Introduction
                              ------------
The "auto_ptr" class template is an extremely important and useful class
that all C++ programmers, both novice and expert alike, should not only
know how to use, but should use on a regular basis whenever using the
heap.  The use of "auto_ptr" is particularly important for ROOT users
because many of the scripting habits we pick up in our interactive use
of ROOT are "no-nos" when it comes time to move our code into compiled
applications and libraries.

For example, taking advantage of cint's useful garbage collecting
abilities is fine for simple interactive use, but ignoring, or
forgetting, your responsibility to manage your use of the heap in
compiled code leads to memory leaks and hard-to-find bugs.  The use of
"auto_ptr" can go a long way in helping you automatically manage your
use of the heap.


                          Results and Summary
                          -------------------
I recently did some experiments which tested how well the "auto_ptr"
class template works with a current version of ROOT.  My results are
that, as of ROOT version 2.22.10 (the most current version of ROOT as I
write this), "auto_ptr" can be used interactively with cint in a limited
way with a few caveats:

  1) Only one of the two forms of calling the "auto_ptr" constructor
     works:

       auto_ptr<Foo> foo( new Foo() );  // OK
       auto_ptr<Foo> foo = new Foo();   // broken
     
  2) "operator->" does not work.

Therefore, as long as you stick to "operator*" for accessing your heap
based objects, "auto_ptr" should work well for you.  However, not having
"operator->" doesn't make the "auto_ptr" smart pointer very smart.
Perhaps this is a straight forward fix for Masaharu.

Therefore, instead of using an "auto_ptr" like this:

   auto_ptr<Foo> foo( new Foo() );
   foo->Print();

You will have to use it like this:

   auto_ptr<Foo> foo( new Foo() );
   (*foo).Print();

or this:

   auto_ptr<Foo> foo0( new Foo() );
   Foo& foo1 = *foo0;
   foo1.Print();

Finally, those parts of "auto_ptr" that do work also work well from both
interpreted and compiled code.


                     Building and Testing Yourself
                     -----------------------------
This tiny package, "root-auto_ptr", demonstrates some simple experiments
of using "auto_ptr" with ROOT.  Perhaps this package might be useful to
the ROOT developers as they work on the template support in cint, and
particularly as they work on adding batter support for the "auto_ptr"
class template.  To build and run the examples, do the following:

  $ gunzip -c root-auto_ptr-0.01.tar.gz | tar -xpvf -
  $ mkdir root-auto_ptr-0.01.build
  $ cd root-auto_ptr-0.01.build
  $ ../root-auto_ptr-0.01/configure
  $ make
  $ make check

I have also provided the file `Makefile.manual' for "stand-alone"
operation.  It provides a subset of the functionality in the Autoconf,
Automake and Libtool files, but is enough to build and run the tests in
a directory separate from the source.  For example, you would use this
Makefile as follows:

  $ ln -s /blah/blah/blah/Makefile.manual Makefile
  $ make check

The point of providing this Makefile is to make it easier to experiment
with the examples.  The Autoconf, Automake and Libtool files provide a
lot of additional functionality that you don't need if you just want to
build and run the examples.  Your build times will be faster if you use
this Makefile, but you may have to edit a few of the "System" and "ROOT"
macros to get the examples to build properly.

Running "make check" runs both compiled versions, and "cint interpreted"
versions, of the tests.

NOTE: cint always returns success (i.e. exit code 0), even when
      interpreted code fails.  This makes it difficult to write a ROOT
      testsuite, so you will have to visually scan the output of the
      tests "by eye" to determine which of the tests actually fail.


                Nitty Gritty Details for ROOT Developers
                ----------------------------------------
The current problem of using "auto_ptr" interactively in cint is that
"operator->" is not resolved properly.  As in all implementations of
"smart pointers", "operator->" must ultimately forward the request to
the pointee.  For example, this is how "operator->" is overloaded in
"auto_ptr" (see the files `auto_ptr.hxx' and `auto_ptr.ixx' for the full
implementation):

  template< class T >
  inline
  T*
  auto_ptr< T >::operator->() const
  {
     return pointee;
  }

Now consider the following code, which, given the implementation of
"operator->" above, should call the member function "Foo::Print()" of
the object "foo":

   auto_ptr<Foo> foo( new Foo() );
   foo->Print();

However, cint doesn't appear to resolve the call to "operator->"
properly, as evidenced by this typical cint error message:

  Error: Can't call auto_ptr<Foo>::Print() in current scope ...

I have tried the following combinations of using the "operator->" member
function of "auto_ptr" with ROOT:

                         +------------------------+----------------------------+
                         | auto_ptr<> interpreted | auto_ptr<Foo> pre-compiled |
+------------------------+------------------------+----------------------------+
|                        |                        |                            |
| class Foo interpreted  |           NO           |             NO             |
|                        |                        |                            |
+------------------------+------------------------+----------------------------+
|                        |                        |                            |
| class Foo pre-compiled |           NO           |             YES            |
|                        |                        |                            |
+------------------------+------------------------+----------------------------+

NOTES:

  1) "NO" means that the combination *does not* work with ROOT.

  2) "YES" means that the combination *does* work with ROOT.

  3) The class "auto_ptr" was taken from Scott Meyers, "More Effective
     C++", 1st edition, (Addison-Wesley, 1996).  I have been using this
     class successfully in compiled projects for many years.

     However, since it is documented that cint doesn't currently support
     "explicit" constructors nor template member functions, I
     conditionalized these two features out of the implementation of
     "auto_ptr" so that it could in principle be used by cint.

  4) The class "Foo" (and classes "Bar" and "Baz" as well) are just
     simple dummy classes whose only purpose is to experiment with
     instantiating an "auto_ptr" with a user-defined type.

  5) In the table above, "interpreted" means that the class is parsed by
     cint (i.e. the class does not reside in a shared library).

  6) In the table above, "pre-compiled" means that the class is compiled
     and loaded into cint from a shared library.  This means that
     "auto_ptr<Foo>" was instantiated and compiled in the same spirit as
     some of the new pre-compiled STL containers in recent versions of
     ROOT (e.g. "vector<int>").


                                Manifest
                                --------
If you want to delve into the examples more deeply, then you will want
to look at the files:

  .rootrc               ROOT configuration file for running the test
                        macros through ROOT (i.e. test_n.cxx, where "n"
                        runs from 01 through 07).
  Bar.cxx \             
  Bar.hxx  \            The classes "Foo", "Bar" and "Baz are just
  Baz.cxx   \           simple dummy classes whose only purpose is to
  Baz.hxx   /           experiment with instantiating an "auto_ptr" with
  Foo.cxx  /            a user-defined type:
  Foo.hxx /
  Makefile.manual       Useful Makefile for building a shared library of
                        the above files.
  README                This file.
  auto_ptr.hxx          auto_ptr definition file
  auto_ptr.ixx          auto_ptr implementation file
  auto_ptr_LinkDef.h    Common instantiations of auto_ptr<> to put into
                        a cint dictionary (i.e. "auto_ptr<Foo>" and
                        "auto_ptr<Bar>").

For the following files, "n" runs from 01 through 07.

  test_n.cxx            auto_ptr test files
  test_n.sh             shell script to run the `test_n.cxx' as a ROOT macro.

                               Miscellany
                               ----------
These experiments were done on a Pentium III system running Linux
(i.e. i686-pc-linux-gnu).  The system's exact configuration is:

  Machine configuration with bug
  ------------------------------
  RedHat Linux 6.0 Intel
  kernel 2.2.5           (rpm version kernel-2.2.5-22)
  glibc 2.1.1            (rpm version glibc-2.1.1-6)
  egcs 1.1.2             (rpm version egcs-1.1.2-12)
  binutils 2.9.1.0.23    (rpm version binutils-2.9.1.0.23-1
  ROOT 2.22.10

--
Matthew D. Langston  <langston@SLAC.Stanford.EDU>
1999-08-13



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:38 MET