Re: Just another SEGV ...

From: Matthew D. Langston (langston@SLAC.stanford.edu)
Date: Thu Aug 19 1999 - 00:34:07 MEST


Hi Volker,

I saw a couple of problems with your C++ code that will definitely cause
you problems.

The first is that you are using "array new" to allocate and initialize
memory for your array of "EMModule", but you aren't using the
corresponding call to "array delete" in the destructor of "EMCalo".
Your destructor should look like this instead:

  EMCalo::~EMCalo()
  {
     delete [] Modules;
  }

You were using "delete Modules;", which the C++ Standard says will
result in undefined behavior.

An easy way to avoid problems like this (i.e. accidentally mixing your
forms of "new", "new []", "delete" and "delete []") is to use the
"auto_ptr" and "auto_array_ptr" class templates.  I have attached my
implementation of an "auto_array_ptr" class template to this e-mail
which you may find helpful.

I've also attached 3 other small files as well (`Foo.hxx', `Foo.cxx' and
`volkner.cxx') which demonstrate how to use an "auto_array_ptr".  This
will currently only work in compiled code, but Masaharu has recently
helped me to get the "auto_ptr" class template to work with interpreted
code.  Hopefully both "auto_ptr" and "auto_array_ptr" will be fully
supported in the next release of ROOT.

The second problem is that you were calling "delete" on your ifstream.
In your code you have:

  void
  EMCalo::ReadCalFile( char* n )
  {
     [snip]

     ifstream setup( n );
  
     [snip]

     setup.close();
     delete setup; 
  }


Since "setup" is not allocated on the heap, you shouldn't be calling
"delete" on it (setup's destructor will run when it leaves scope).

FYI, whenever I get a segvio from cint, I always compile my code (not
linking it, mind you), just to let the compiler catch my errors.  Your
C++ compiler would have caught the errors that I spotted by eye (there
may be others that I didn't catch as well).  Once the compiler is happy,
my code typically runs just fine in the interpreter.

This may not be the ROOT development model we would like (i.e. that of
getting our code to work first in the interpreter, and then move it to
compiled code for efficiency), but it is a fact of life (for me,
anyway).

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


#ifndef EXCEPTIONHELPERS_ARRAY_AUTO_PTR
#define EXCEPTIONHELPERS_ARRAY_AUTO_PTR

// auto_array_ptr -- inspired by from Scott Meyers, "More Effective
//                   C++", 1st edition, (Addison-Wesley, 1996)
// 
//
// Copyright (C) 1998, 1999 Matthew D. Langston <langston@SLAC.Stanford.EDU>
//
// This file is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at
// your option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this file; if not, write to:
//
//   Free Software Foundation, Inc.
//   Suite 330
//   59 Temple Place
//   Boston, MA 02111-1307, USA.

// Unfortunately, most compilerss don't support `explicit' yet.
#ifndef HAVE_EXPLICIT
#define explicit
#endif


namespace MDL
{
   template< class T >
      class auto_array_ptr
      {
         public:

            // See Item 5 for a description of "explicit".
#ifndef __CINT__
            explicit
#endif
            auto_array_ptr( T* p = 0 );
  
            // Unfortunately, most compilerss don't support mwmber
            // templates yet either.
#ifdef HAVE_MEMBER_TEMPLATES
            // Copy constructor member template (see Item 28):
            // initialize a new auto_array_ptr with any compatible
            // auto_array_ptr.
            template< class U > 
#ifndef __CINT__
            explicit
#endif
            auto_array_ptr( auto_array_ptr< U >& rhs );
#else
#ifndef __CINT__
            explicit
#endif
            auto_array_ptr( auto_array_ptr< T >& rhs );
#endif

            ~auto_array_ptr();
  
#ifdef HAVE_MEMBER_TEMPLATES
            // Assignment operator member template (see Item 28): assign
            // from any compatible auto_array_ptr.
            template< class U >
            auto_array_ptr< T >& operator=( auto_array_ptr< U >& rhs );
#else
            auto_array_ptr< T >& operator=( auto_array_ptr< T >& rhs );
#endif

            T& operator*()  const; // see Item 28
            T* operator->() const; // see Item 28
  
            // Return value of current dumb pointer.
            T* get() const;
  
            // Relinquish ownership of current dumb pointer and return
            // its value.
            T* release();
  
            // Delete owned pointer; assume ownership of p.
            void reset( T* p = 0 );

            static void remove( T*& p );

         private:

            T* pointee;
      };
};


// Include the template definitions.
#include "auto_array_ptr.ixx"

#endif  // EXCEPTIONHELPERS_AUTO_ARRAY_PTR


// -*- Mode: C++ -*-
// Copyright (C) 1998, 1999 Matthew D. Langston <langston@SLAC.Stanford.EDU>
//
// This file is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at
// your option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this file; if not, write to:
//
//   Free Software Foundation, Inc.
//   Suite 330
//   59 Temple Place
//   Boston, MA 02111-1307, USA.

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif


template< class T >
inline
MDL::auto_array_ptr< T >::auto_array_ptr( T* p )
   : pointee( p )
{}


template< class T >
#ifdef HAVE_MEMBER_TEMPLATES
template< class U >
inline
MDL::auto_array_ptr< T >::auto_array_ptr( auto_array_ptr< U >& rhs )
#else
inline
MDL::auto_array_ptr< T >::auto_array_ptr( auto_array_ptr< T >& rhs )
#endif
   : pointee( rhs.release() )
{}


template< class T >
inline
MDL::auto_array_ptr< T >::~auto_array_ptr()
{
   delete[] pointee;
}


template< class T >
#ifdef HAVE_MEMBER_TEMPLATES
template< class U >
#endif
inline
MDL::auto_array_ptr< T >&
#ifdef HAVE_MEMBER_TEMPLATES
MDL::auto_array_ptr< T >::operator=( auto_array_ptr< U >& rhs )
#else
MDL::auto_array_ptr< T >::operator=( auto_array_ptr< T >& rhs )
#endif
{
   if ( this != &rhs )
   {
      reset( rhs.release() );
   }
   
   return *this;
}


template< class T >
inline
T&
MDL::auto_array_ptr< T >::operator*() const
{
   return *pointee;
}


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


template< class T >
inline
T*
MDL::auto_array_ptr< T >::get() const
{
   return pointee;
}


template< class T >
inline
T*
MDL::auto_array_ptr< T >::release()
{
   T* oldPointee = pointee;
   pointee = 0;
   return oldPointee;
}


template< class T >
inline
void
MDL::auto_array_ptr< T >::reset( T* p )
{
   T oldPointee = pointee;
   pointee = p;
   delete[] oldPointee;
}


template< class T >
inline
void
MDL::auto_array_ptr< T >::remove( T*& p )
{
   T* tempPointee = p;
   p = 0;
   delete[] tempPointee;
}


#ifndef FOO
#define FOO


class Foo
{
   public:

      Foo();
      virtual ~Foo();

      void Print();

   private:

      static int fTotal;
      int fn;
};


#endif // FOO


#include "Foo.hxx"
#include <iostream>


int Foo::fTotal = 0;


Foo::Foo()
{
   fn = fTotal++;
}
      

Foo::~Foo()
{
   cout << fn << " leaving scope." << endl;
}
      
      
void
Foo::Print()
{
   cout << "Foo: Hello, world." << endl;
}


#include "Foo.hxx"
#include "auto_array_ptr.hxx"
using namespace MDL;


int
main( int argc, char* argv[] )
{
   auto_array_ptr<Foo> foo_temp( new Foo[ 10 ] );
   Foo* foo_array = foo_temp.get();
   foo_array[ 3 ].Print();
}

// Local variables:
//  compile-command: "g++ -Wall volkner.cxx Foo.cxx -o volkner"
// End:



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