With regard to the following code. I have only included Memory.h in ClassA.cpp, but ClassB.cpp still seems to be able to see it. How do i make it so that ClassB does not use the operator new in Memory.h, but the usual one?

Am am I right in thinking it has something to do with external linkage? But in that case, wouldnt i still have to declare an extern func signature for new in ClassB.cpp?

Basically, Im wanting it so that my overide of operator delete is only used in the source files I include Memory.h in.

//Memory.h

#pragma once

#include <iostream>

void* operator new ( size_t size );
void operator delete ( void* p, int size );
//Memory.cpp
#include "Memory.h"

void* operator new ( size_t size )
{
	std::cout << " Allocating " << size << " bytes" << std::endl;
	return 0;
}

void operator delete ( void* p, int size )
{
	std::cout << " Deallocating " << size << " bytes" << std::endl;
}
//ClassA.h

#pragma once

class ClassA
{
public:
	void Hello();
};
//ClassA.cpp

#include "ClassA.h"
#include "Memory.h"

void ClassA::Hello(){
	new char();
}
//ClassB.h

#pragma once

class ClassB
{
public:
	void Hello();
};
//ClassB.cpp

#include "ClassB.h"

void ClassB::Hello(){
	new char();
}

>Am am I right in thinking it has something to do with external linkage?
Something like that. The following operators are implicitly declared in every file:

void *operator new ( size_t bytes );
void *operator new[] ( size_t bytes );
void operator delete ( void* );
void operator delete[] ( void* );

If you override them with a matching definition, all uses will refer to your definition, not the implementation's.

>Basically, Im wanting it so that my overide of operator delete
>is only used in the source files I include Memory.h in.

I strongly recommend not overriding the global new and delete operators. It's tricky to get right and easy to be surprised. Why exactly do you need this behavior?

I just wanted to some tracking, such as how memory is allocated, when and how often

If you don't want to track allocations globally (as in everywhere), then you'd be better off only overloading new and delete for specific classes, or using an allocation class that makes your tracking needs explicit:

#include <cstddef>
#include <iostream>

namespace jsw {
  namespace memory {
    class tracked_heap {
      // Single object counters
      int _n_soalloc;
      int _n_sofree;

      // Dynamic array counters
      int _n_daalloc;
      int _n_dafree;
    public:
      tracked_heap()
        : _n_soalloc ( 0 ), _n_sofree ( 0 ),
          _n_daalloc ( 0 ), _n_dafree ( 0 )
      {}

      int single_alloc() const { return _n_soalloc; }
      int single_free() const { return _n_sofree; }
      int array_alloc() const { return _n_daalloc; }
      int array_free() const { return _n_dafree; }

      template <typename T>
      T *alloc ( std::size_t n = 0 )
      {
        T *p = 0;

        if ( n <= 0 ) {
          p = new T;
          ++_n_soalloc;
        }
        else {
          p = new T[n];
          ++_n_daalloc;
        }

        return p;
      }

      void free ( void *p, std::size_t n = 0 )
      {
        if ( n <= 0 ) {
          delete p;
          ++_n_sofree;
        }
        else {
          delete[] p;
          ++_n_dafree;
        }
      }
    };
  }
}

namespace {
  jsw::memory::tracked_heap heap;
}

int main()
{
  std::cout<<'('<<heap.single_alloc() <<','<< heap.array_alloc() <<")\n"
           <<'('<<heap.single_free() <<','<< heap.array_free() <<")\n\n";

  int *p = heap.alloc<int>();
  int *q = heap.alloc<int> ( 5 );

  std::cout<<'('<<heap.single_alloc() <<','<< heap.array_alloc() <<")\n"
           <<'('<<heap.single_free() <<','<< heap.array_free() <<")\n\n";

  heap.free ( p );
  heap.free ( q, 5 );

  std::cout<<'('<<heap.single_alloc() <<','<< heap.array_alloc() <<")\n"
           <<'('<<heap.single_free() <<','<< heap.array_free() <<")\n\n";

  bool so_leak = heap.single_alloc() - heap.single_free() != 0;
  bool da_leak = heap.array_alloc() - heap.array_free() != 0;

  std::cout<< std::boolalpha 
           <<"Single Object Leaks: "<< so_leak <<'\n'
           <<"Dynamic Array Leaks: "<< so_leak <<'\n';
}

Thanks for the reply. Yours seems like an interesting way to go about it. But it not so much that I dont want to track allocations globally, ... I do. I just dont want to track them in certain source files.

>But it not so much that I dont want to track allocations globally, ... I
>do. I just dont want to track them in certain source files.

You realize that those two statements are contradictory, right? If you want to do it globally, that means every file, the whole program. If you don't want to do it globally, which is clearly the case, you can override (or not) the global operators and then use an alternative strategy (such as the one I suggested) for those "certain" files.

If you override them with a matching definition, all uses will refer to your definition, not the implementation's.

in fact, both implicit & explicit implemations for new & delete are called when you use them. new & delete are strange operators. I have a few examples about the order of calling for implicit & explicit implementation. but I'm too lazy to try to find them ;)
but I'll post if I find...

Edited 6 Years Ago by CppBuilder2006: n/a

I looked at my examples. they were about overloading new & delete operators inside a class. sorry I was wrong :$.
there are cases that someone needs to edit or delete his posts. but I don't arg..

Edited 6 Years Ago by CppBuilder2006: n/a

This article has been dead for over six months. Start a new discussion instead.