Macro needed

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Yogesh

    #1

    Macro needed

    Hi List,
    I am overloading new and delete globally for memory leak detection.

    void* operator new(std::size_t s, const char * file , int inLine) ;
    ->case1
    void* operator new[](std::size_t s, const char * file , int inLine);
    ->case 2

    I implement the above two functions using malloc. Now to replace all
    occurances of
    standard new with my above new operator I use the below macro.


    #define DEBUG_NEW new(__FILE__, __LINE__)
    #define new DEBUG_NEW

    This works for first case.
    My question is can I define a Macro in a similar way for second case
    also?
    if so, how?
    if not, any work around to replace all occurances of operator new[]
    with my operator?

    ---
    Thanks,
    Yogesh Kini

  • Victor Bazarov

    #2
    Re: Macro needed

    Yogesh wrote:[color=blue]
    > I am overloading new and delete globally for memory leak detection.
    >
    > void* operator new(std::size_t s, const char * file , int inLine) ;
    > ->case1
    > void* operator new[](std::size_t s, const char * file , int inLine);
    > ->case 2
    >
    > I implement the above two functions using malloc. Now to replace all
    > occurances of
    > standard new with my above new operator I use the below macro.
    >
    >
    > #define DEBUG_NEW new(__FILE__, __LINE__)
    > #define new DEBUG_NEW
    >
    > This works for first case.
    > My question is can I define a Macro in a similar way for second case
    > also?[/color]

    Doesn't it work for the second case as well?
    [color=blue]
    > if so, how?
    > if not, any work around to replace all occurances of operator new[]
    > with my operator?[/color]

    Uh... I am sorry, I probably don't understand the problem. If you
    have

    int * pi = new int(666);

    you now get

    int * pi = new("somefile.c c", 42) int(666);

    , right? So, if you have to allocate an array,

    int * parr = new int[666];

    would it just as well be

    int * parr = new("somefile.c c", 42) int[666];

    ??? What's different about 'new[]'? Or were you just afraid to try?

    V

    Comment

    • mlimber

      #3
      Re: Macro needed

      Yogesh wrote:[color=blue]
      > Hi List,
      > I am overloading new and delete globally for memory leak detection.
      >
      > void* operator new(std::size_t s, const char * file , int inLine) ;
      > ->case1
      > void* operator new[](std::size_t s, const char * file , int inLine);
      > ->case 2
      >
      > I implement the above two functions using malloc. Now to replace all
      > occurances of
      > standard new with my above new operator I use the below macro.
      >
      >
      > #define DEBUG_NEW new(__FILE__, __LINE__)
      > #define new DEBUG_NEW
      >
      > This works for first case.
      > My question is can I define a Macro in a similar way for second case
      > also?
      > if so, how?
      > if not, any work around to replace all occurances of operator new[]
      > with my operator?
      >
      > ---
      > Thanks,
      > Yogesh Kini[/color]

      If we ignore the bigger problem, I think your #defines would work for
      both new and new[] since you'd invoke it like this:

      int *ptr = new int(42);
      int *array = new int[ 100 ];

      With your macros, these would become

      int *ptr = new("MyFile.cpp ", 10) int(42);
      int *array = new("MyFile.cpp ", 11) int[ 100 ];

      However, let me suggest that your approach of using __FILE__ and
      __LINE__ won't work. See this recent discussion for details:



      Consider using an existing library for your platform to look for leaks,
      rather than writing your own. (Google for them.) Also, the thorough use
      of smart pointers (e.g., std::auto_ptr, boost::scoped_p tr, and
      boost::shared_p tr) virtually eliminates the possibility of memory
      leaks. Consider using such practices.

      Cheers! --M

      Comment

      • Yogesh

        #4
        Re: Macro needed

        Hi ,
        Thanks for prompt reply.
        I was not aware that though "new" and "new[]" are different operators,
        they are
        translated in the same(similar) way by the compiler.
        [color=blue]
        > Consider using an existing library for your platform to look for leaks,
        > rather than writing your own. (Google for them.) Also, the thorough use
        > of smart pointers (e.g., std::auto_ptr, boost::scoped_p tr, and
        > boost::shared_p tr) virtually eliminates the possibility of memory
        > leaks. Consider using such practices.[/color]

        I am looking into existing code, so replacing normal pointers with
        std::auto_ptr,
        boost::scoped_p tr is tedious job. Also I felt it would be a good
        experience to do
        it myself, than using a existing tool.

        [color=blue]
        > However, let me suggest that your approach of using __FILE__ and
        > __LINE__ won't work. See this recent discussion for details:[/color]

        Dont know, why you say that. Please look at the code below. It seems to
        work fine.
        Mac OSX 10.4.2, gcc 4.0.1(Xcode)

        Let me know if I am doing something wrong.
        I call void "PrintMemoryDum p()" at application Shutdown.

        ---------------------------------MemoryTest.h(Be gin)--------------------------------------------------

        #ifndef _MEMORY_TEST_H_
        #define _MEMORY_TEST_H_

        #include <new>
        #include <stdio.h>
        #include <stdlib.h>

        void* operator new(std::size_t s, const char * file , int inLine) ;
        void operator delete(void*) throw();

        void* operator new[](std::size_t s, const char * file , int inLine);
        void operator delete[](void*) throw();

        void PrintMemoryDump ();

        #define DEBUG_NEW new(__FILE__, __LINE__)
        #define new DEBUG_NEW

        #endif

        ---------------------------------MemoryTest.h(En d)--------------------------------------------------



        ---------------------------------MemoryTest.cpp( Begin)--------------------------------------------------
        #include "MemoryTest .h"


        #ifdef DEBUG_NEW
        #define DEBUG_NEW new
        #endif

        struct tMemoryBlock
        {
        char _file[256];
        int _lineNumber, _numBytes;
        void * _pointer;
        bool _deleted;
        tMemoryBlock * next;
        };

        tMemoryBlock* head = NULL;

        void AddBlock(tMemor yBlock ** inBlock)
        {
        if(head == NULL)
        {
        head = *inBlock;
        return;
        }
        tMemoryBlock * ptr = head;
        while(ptr ->next != NULL)
        {
        ptr = ptr->next;
        }
        ptr ->next = *inBlock;
        }

        void RemoveBlock(voi d * inptr)
        {
        if(head == NULL) return;
        tMemoryBlock * ptr = head;
        while(ptr != NULL)
        {
        if(ptr->_pointer == inptr)
        {
        ptr->_deleted = true;
        }
        ptr = ptr->next;
        }
        }

        void PrintMemoryDump ()
        {
        tMemoryBlock * ptr = head;
        while(ptr != NULL)
        {
        if(ptr->_deleted == false)
        {
        fprintf(stderr, "**MEM LEAK** %s %d\n",ptr->_file,ptr->_lineNumber) ;
        }
        ptr =ptr->next;
        }
        ptr = head->next; tMemoryBlock * dptr= head;

        while(ptr != NULL)
        {
        free(dptr);
        dptr = ptr;
        ptr = ptr->next;
        }
        }

        void* operator new(std::size_t s, const char * file , int inLine)
        {
        void *ptr = (void *)malloc(s);
        tMemoryBlock * t = (tMemoryBlock*) malloc(sizeof(t MemoryBlock));
        strcpy(t->_file, file);
        t->_lineNumber = inLine;
        t->_deleted = false;
        t->_numBytes = s;
        t->next = NULL;
        t->_pointer = ptr;

        AddBlock(&t);

        return(ptr);
        }

        void operator delete(void* p) throw()
        {
        RemoveBlock(p);
        free(p);
        }

        void* operator new[](std::size_t s, const char * file , int inLine)
        {

        void *ptr = (void *)malloc(s);
        tMemoryBlock * t = (tMemoryBlock*) malloc(sizeof(t MemoryBlock));
        strcpy(t->_file, file);
        t->_lineNumber = inLine;
        t->_deleted = false;
        t->_numBytes = s;
        t->next = NULL;
        t->_pointer = ptr;

        AddBlock(&t);
        return(ptr);
        }

        void operator delete[](void*p) throw()
        {
        RemoveBlock(p);
        free(p);
        }

        #define new DEBUG_NEW
        #define DEBUG_NEW new(__FILE__, __LINE__)


        ---------------------------------MemoryTest.cpp( End)--------------------------------------------------

        Comment

        • mlimber

          #5
          Re: Macro needed

          Yogesh wrote:[color=blue][color=green]
          > > Consider using an existing library for your platform to look for leaks,
          > > rather than writing your own. (Google for them.) Also, the thorough use
          > > of smart pointers (e.g., std::auto_ptr, boost::scoped_p tr, and
          > > boost::shared_p tr) virtually eliminates the possibility of memory
          > > leaks. Consider using such practices.[/color]
          >
          > I am looking into existing code, so replacing normal pointers with
          > std::auto_ptr,
          > boost::scoped_p tr is tedious job. Also I felt it would be a good
          > experience to do
          > it myself, than using a existing tool.[/color]

          It would likely be a good learning exercise, and I commend it to you
          for your edification. However, if this is for production code, I would
          suggest using an existing library since there are can be quite a few
          subtleties involved. (For similar reasons, Bjarne Stroustrup recommends
          in TC++PL 6.2.6.2 that anyone wishing to implement a garbage collector
          except as an educational exercise should get one that has already been
          written and tested.)
          [color=blue][color=green]
          > > However, let me suggest that your approach of using __FILE__ and
          > > __LINE__ won't work. See this recent discussion for details:[/color]
          >
          > Dont know, why you say that. Please look at the code below. It seems to
          > work fine.
          > Mac OSX 10.4.2, gcc 4.0.1(Xcode)
          >
          > Let me know if I am doing something wrong.
          > I call void "PrintMemoryDum p()" at application Shutdown.
          >
          > ---------------------------------MemoryTest.h(Be gin)--------------------------------------------------
          >
          > #ifndef _MEMORY_TEST_H_
          > #define _MEMORY_TEST_H_
          >
          > #include <new>
          > #include <stdio.h>
          > #include <stdlib.h>
          >
          > void* operator new(std::size_t s, const char * file , int inLine) ;
          > void operator delete(void*) throw();
          >
          > void* operator new[](std::size_t s, const char * file , int inLine);
          > void operator delete[](void*) throw();
          >
          > void PrintMemoryDump ();
          >
          > #define DEBUG_NEW new(__FILE__, __LINE__)
          > #define new DEBUG_NEW
          >
          > #endif
          >
          > ---------------------------------MemoryTest.h(En d)--------------------------------------------------[/color]

          [code snipped]

          One of the subtleties that I have in mind is that, when new fails (e.g.
          if a constructor throws an exception), the compiler implicitly looks
          for a corresponding delete operator with a similar signature to the
          new, but you have not provided such an operator, which means you would
          have a very tricky memory leak. See this FAQ:

          http://www.parashift.c om/c++-faq-lite/dtors.html#faq-11.14

          which describes what happens behind the scenes when you call new. Note
          particularly its "Problem #1". (The FAQ discusses placement new, which
          is similar to your "new with parameter" usage here.)

          In any case, I was assuming that you were using the filename/line to be
          the block lookup key, which you are not. So you've already avoided one
          danger present in the previously cited thread.

          BTW, I only looked cursorily at your code, but I did notice that
          AddBlock() doesn't need a double pointer passed in.

          Cheers! --M

          Comment

          Working...