Global new operator overloading - c++

I have read about new and delete overloading for memory tracking in How_To_Find_Memory_Leaks
I defined these global operators:
inline void* __cdecl operator new( unsigned int size, const char *file, int line ) {
void* ptr = malloc( size );
AddTrack((DWORD)ptr, size, file, line);
return ptr;
}
inline void* __cdecl operator new( unsigned int size, void* ptr, const char *file, int line ) {
return ptr;
}
It works well with new and new[] operators, but i have a problem with placement new ( second one ). My define look like:
#define new new( __FILE__, __LINE__)
#define new(x) new( x, __FILE__, __LINE__)
They work separately. But when i try to use them both there are errors appear. As I understand they substitute each other. I know I can have macro with variable number of arguments like this:
#define new( ... ) new( __VA_ARGS__, __FILE__, __LINE__)
But I need the same macro with and without arguments at all, so both new-s in these lines substitute right:
g_brushes = new Brush[ num_brushes ];
...
new( &g_brushes[i] )Brush(sides);

If you decide to walk the dark path of overriding the global new, you have to make sure you consider all of the following scenarios:
new Foo; // 1
new Foo[10]; // 2
new (std::nothrow) Foo; // 3
new (p) Foo; // 4 - placement, not overridable
(Foo*) ::operator new(sizeof(Foo)); // 5 - direct invocation of the operator
And it should be possible to be able to handle all the above except for the last. Shudder.
The necessary knol and the sleight of hand is that your macro should end with new. When your macro ends with new, you can delegate the different ways it can be invoked to new itself.
Here's one, non-thread safe way to proceed. Define a type to capture the context of the invocation, so we will be able to retrieve this context later in the operator itself,
struct new_context {
new_context(const char* file, const int line)
: file_(file), line_(line) { scope_ = this; }
~new_context() { scope_ = 0; }
static new_context const& scope() { assert(scope_); return *scope_; }
operator bool() const { return false; }
const char* file_;
const int line_;
private:
static new_context* scope_;
};
Next, define your override to create a new_context temporary just before the invocation,
#define new new_context(__FILE__, __LINE__) ? 0 : new
using the ternary operator conditional assignment to evaluate an expression before delegating to the operator new, notice that it is where the operator bool that we have defined above comes handy.
Then inside your new overrides (I'll use standard C++98 here instead of the MSC C++), all you have to do is to retrieve the context:
void* operator new (std::size_t size) throw (std::bad_alloc) {
std::cout
<< "new"
<< "," << new_context::scope().file_
<< ":" << new_context::scope().line_
<< std::endl;
return 0;
}
This approach will deal with all the cases 1-4 from above, and what's important and can be easily overlooked is that in case 4 where your overloads are not invoked, as you cannot replace placement new (§18.4.​1.3), you still know that placement new took place because new_context will be created and destroyed.
To summarise, you don’t need to modify what follows after the new operator, so all possible syntaxes remain valid. And the other point is that the new_context object temporary is going to be kept alive until the end of the expression the operator participates in, so you are safe to obtain it from a global singleton.
See a gcc example live. Adapting to MSC is left to the reader.

Related

Is it possible to use custom allocation operator to create a STACK object?

Ok, if I want to create a heap object with a custom new operator, I know that I need to overload the new operator like this:
void* operator new(size_t size, int unused)
{
void* ptr = malloc(size);
//some custom code
return ptr;
}
And then, if I want to create a heap object using this overloaded operator I would do this:
SomeClass* a = new(0) SomeClass;
The question is: can I do something like this to create a stack object?
I agree with other answers that you probably don't need this but you could do it. See sample code below, just allocate the memory ahead of time and pass it into placement new. You might want to do this if you are using the array new[] form where you might do something like
void *rawMemory = operator new[](25*sizeof(std::stack));
if you had an array of stacks that you had a factory method that managed the resources or something. Either way it depends on your application and use cases. Below shows a simple example
#include <iostream>
#include <stack>
int main ( int argc, char *argv[])
{
void *rawMemory = operator new(sizeof(std::stack<unsigned int>));
std::stack<unsigned int> *s = new (rawMemory) std::stack<unsigned int>;
s->push(10);
std::cout << s->top() << std::endl;
return 0;
}
Second example using the array version, which seems more useful where you may be managing 25 different stacks and handing them to clients. Also, answering your comment. See that the container is defined in the stack definition this time, in this case I am using a vector for the container. Stack is a container but it has an underlying container that defaults to deque
#include <iostream>
#include <stack>
#include <vector>
int main ( int argc, char *argv[])
{
typedef std::stack<unsigned int,std::vector<unsigned int> > StackType;
void *rawMemory = operator new[](25*sizeof(StackType));
StackType *stacks = static_cast<StackType*> (rawMemory);
// allocate
for ( unsigned int i = 0; i < 25; ++i )
{
new (stacks+i) StackType;
}
stacks[1].push(10);
std::cout << stacks[1].top() << std::endl;
// don't forget to delete or smart resize
for ( int i = 24; i >= 0; --i )
{
StackType x;
std::swap ( x, stacks[i] );
}
return 0;
}
You can define a macro like this:
#define STACK_NEW(T) new (alloca(sizeof(T))) T
that uses placement new and alloca() to allocate a block on the stack and construct an object of type T on top of it. You can also define an array version:
#define STACK_NEW_ARRAY(T, n) new (alloca(n * sizeof(T))) T
You'd use this macro in the following ways:
int * p = STACK_NEW(int);
MyObj * q = STACK_NEW(MyObj) (my, constructor, parameters);
int * r = STACK_NEW_ARRAY(int, 42);
You'll have destruct these objects manually:
q->~MyObj();
Deleting them will have undefined behavior.
WARNING: This whole facility is very unsafe. I'd strongly recommend against having such systematically dangerous tools in your codebase. As far as I can see, there is no safe way to use it and it will cause you pain!

Multiple arguments to C++ placement new 'constructor'

In order to do some custom memory tracking (leak prevention, corruption detection), I'm having to use placement new to create C++ objects, which works fine - but I'm struggling to figure out how I can pass arguments to the constructor, since it's called from a macro (so the file + line can be provided automatically).
The function:
template <typename T>
T*
cpp_new(
const char *file,
size_t line
)
{
T *n = (T*)tracked_allocate(&memory_context, sizeof(T), file, line);
if ( n )
{
construct(n);
}
else
{
throw std::bad_alloc();
}
return n;
}
This is called via the macro:
#define new_object(type) cpp_new<type>(__FILE__, __LINE__)
Placemented new:
template <typename T>
void
construct(
T *obj
)
{
obj = new (obj) T;
}
The va_list macros would cover the expansion for the variable number of arguments, only I don't want to supply the number of arguments the constructor has, removing va_arg(), and can't use va_start(), since it expects a format.
This went a little over my head: http://www.drdobbs.com/cpp/calling-constructors-with-placement-new/232901023?pgno=2
Is there any way I can use __VA_ARGS__ from new_object and pass them into the construct function? Each object only has one constructor, but there are many different types of objects taking different parameters, so I want to remove as much manual maintenance as possible.
Or is there just a better way in general of doing what I'm attempting!
You should not deal with the construct-if-allocation-succeeded. That's the job of a new-expression. It does that correctly, as a transaction-like operation: either all succeeds, or cleanup is performed before the exception is propagated.
So, relieved of that responsibility, the job of your macro is to do that which only macros can do, namely picking up the filename and line.
Those items can/should be passed to allocator function, which then technically is a "placement new", although here it will not construct in-place: it's a placement new merely because it has extra, user-defined arguments, like this:
bool hopefully( bool const c ) { return c; }
template< class X >
bool throw_( X const& x ) { throw x; }
void* operator new( size_t const size, char const* const filename, int const linenum )
{
void* const p = tracked_allocate( &memory_context, size, filename, linenum );
hopefully( p != 0 )
|| throw_( std::bad_alloc() )
return p;
}
You need to define a corresponding placement deallocation function, or else a new expression will fail to deallocate when a constructor throws:
void operator delete( void* const p )
{
// Your custom deallocation.
}
void operator delete( void* const p, char const*, int )
{
::operator delete( p );
}
Now your macro just needs to provide the relevant placement arguments, like this:
#define SOURCE_LINE_INFO __FILE__, __LINE__
Then you can just say, like,
new (SOURCE_LINE_INFO) MyType( arg1, arg2, arg3 )
For a more reusable solution consider defining a struct to hold the filename and line number. Then the macro reduces to constructing an instance of that type, and can be used more generally. In particular, it can then be used for logging calls.

Am I Deleting my struct Properly?

This is a homework assignment. The Field container was the assignment from a week ago, and now I'm supposed to use the Field container to act as a dynamic array for a struct NumPair which holds two char * like so:
struct NumPair
{
char *pFirst, *pSecond;
int count;
NumPair( char *pfirst = "", char *psecond = "", int count = 0)
: pFirst(strdup(pfirst)), pSecond(strdup(psecond)), count(count)
{ }
NumPair( const NumPair& np )
: count(np.count), pFirst(strdup(np.pFirst)), pSecond(strdup(np.pSecond))
{ }
NumPair& operator=( const NumPair& np )
{
if(this != &np)
{
pFirst = strdup(np.pFirst);
pSecond = strdup(np.pSecond);
count = np.count;
}
return *this;
}
and the Field container
Field<NumPair> dict_;
The homework requires the use of char *, and not string, so that we can get better with all this low-level stuff. I've already had some question about char to wchar_t conversions, etc.
Now I have a question as to whether or not I'm destructing the NumPair properly. The scenario is as follows:
1) Field destructor gets called
template <class T>
Field<T>::~Field()
{
delete[] v_;
}
2) Delete calls the destructor of every element NumPair in v_;
~NumPair()
{
free(pFirst);
free(pSecond);
}
Is this okay? I haven't really read too many articles about mixing and matching elements created on the heap and free-store as we wish. I figure as long as I don't use delete on an improper malloc'ed element, I should be fine.
However, I don't know the entire intricacies of the delete command, so I'm wondering whether or not this is valid design, and what I could do to make it better.
Also, of course this isn't. I'm getting an error of the type:
This may be due to a corruption of the heap and points to dbgheap
extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
const void * pUserData
)
{
if (!pUserData)
return FALSE;
if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
return FALSE;
return HeapValidate( _crtheap, 0, pHdr(pUserData) ); // Here
}
Again, how could I improve this without the use of string?
FIELD CTOR/Copy Ctor/Assignment
template <class T>
Field<T>::Field()
: v_(0), vused_(0), vsize_(0)
{ }
template <class T>
Field<T>::Field(size_t n, const T &val)
: v_(0), vused_(n), vsize_(0)
{
if(n > 0)
{
vsize_ = 1;
while(vsize_ < n)
vsize_ <<= 1;
v_ = new T[vsize_];
std::fill(v_, (v_ + vused_), val);
}
}
template <class T>
Field<T>::Field(const Field<T> &other)
: v_(new T[other.vsize_]), vsize_(other.vsize_), vused_(other.vused_)
{
std::copy(other.v_, (other.v_ + other.vused_), v_);
}
template <class T>
Field<T>& Field<T>::operator =(const Field<T> &other)
{
this->v_ = other.v_;
this->vused_ = other.vused_;
this->vsize_ = other.vsize_;
return *this;
}
FIELD MEMBERS
T *v_;
size_t vsize_;
size_t vused_;
Your copy constructor (of Field<>) seems OK, but the operator= is problematic.
Not only does it leak memory (what happens to the original v_?), but after that, two instances of Field<> hold a pointer to the same block of memory, and the one that is destructed first will invalidate the others v_ - and you can't even tell whether that has happened.
It's not always easy to decide how to deal with operator= - some think that implicit move semantics are okay, but the rest of us see how that played out with the majority of people, with std::auto_ptr. Probably the easiest solution is to disable copying altogether, and use explicit functions for moving ownership.
Your string handling in NumPair looks ok (strdup + free) and your Field container delete[] looks okay but it's hard to say because you don't show what v_ is.
eq mentions in a comment that you should also beware of how you are copying NumPairs. By default, C++ will give you an implicit member-wise copy constructor. This is where a RAII type like std::string makes your life easier: Your std::string containing struct can be copied without any special handling on your part and memory referenced in the string will be taken care of by the string's copy. If you duplicate your NumPair (by assigning it or returning it from a function for example) then the destruction of the temporary will free your strings out from under you.
Your copy constructor for Field just copies the pointers in v_. If you have two copies of a Field, all of the NumPairs in v_ will be deleted when the first Field goes out of scope, and then deleted again when the second one does.

Not copying char arrays, function swap doesnt compile correctly and stringPtr is not modified

//In header file: class definition:
class myString
{
public:
myString(void);
myString(const char *str);
myString(const myString &); //copy constructor
~myString(void); //destructor
void swap(myString &from);
private:
char *stringPtr;
int stringLen;
};
//in cpp file, defining them member functions
myString::myString(const char *str)
{
stringLen = strlen(str);
stringPtr = new char[stringLen+1];
strcpy(stringPtr,str);
cout << "constructor with parameter called"<<endl;
}
myString::myString(const myString &str)
{
stringPtr = new char[str.stringLen +1];
strcpy(stringPtr,str.stringPtr);
cout << "copyconstructor"<<endl;
}
void myString::swap(myString &from)
{
myString buffer(from);
int lengthBuffer = from.stringLen;
from = new char[stringLen+1];
from.stringLen = stringLen;
strcpy(from.stringPtr, stringPtr);
stringPtr = new char[lengthBuffer+1];
stringLen = lengthBuffer;
strcpy(stringPtr,buffer.stringPtr);
}
You can't modify a reference. Even if you replace it with a pointer modifying a pointer will not modify an object pointed to. Instead you need to work through the reference - just swap the fields.
void myString::swap(myString &from)
{
std::swap( stringLen, from.stringLen );
std::swap( stringPtr, from.stringPtr );
}
the above is using std::swap() as suggested by user sbi in comments. This is completely equivalent to the following (just for illustration, don't reinvent STL):
void myString::swap(myString &from)
// First remember own length and pointer
const int myOldLen = stringLen;
char* myOldPtr = stringPtr;
// now copy the length and pointer from that other string
stringLen = from.stringLen;
stringPtr = from.stringPtr;
// copy remembered length and pointer to that other string
from.StringLen = myOldLen;
from.StringPtr = myOldPtr;
// done swapping
}
Both will work even when called fro self-swapping:
myString string;
string.swap( string );
You have already gotten a few good answers concerning the errors in you myString::swap() function. Yet, I'd like to add another one. There's some many things wrong with that function, I first found it hard to think of where to begin. But then I realized that you fail on some fundamental issue which I'd like to point out:
As a convention, a function called swap is expected to perform its task
in O(1)
without ever throwing an exception.
(Yes, I know, there are exceptions: std::tr1::array<>::swap(). But those should be very well justified.) Your implementation fails on both accounts. It is O(n) (strcpy) and might throw an exception (new) -- and it does so unnecessarily and without justification.
When you look at myString, you'll see that it only has two pieces of member data, which both are of built-in type. That means swapping two objects of this class is really simple to do while keeping to the conventions mentioned above: just swap the member data. That's as simple as calling std::swap on them:
void myString::swap(myString &from)
{
std::swap(this->stringPtr,from.stringPtr);
std::swap(this->stringLen,from.stringLen);
}
This is will never fail (swapping two pointers and two integers cannot fail), executes in O(1), is very easy to understand (well, once you get a grip on that swapping, anyway; it is an idiomatic form of implementing a class-specific swap function), and consists of two lines of code calling something well-tested in the standard library instead of 8 lines of code doing error-prone (and, in your case, erroneous) manual memory management.
Note 1: Once you've done this, you should specialize std::swap to call your implementation for your class:
namespace std { // only allowed for specializing function templates in the std lib
template<>
inline void std::swap<myString>(myString& lhs, myString& rhs)
{
lhs.swap(rhs);
}
Note 2: The best (simple, exception-safe, and self-assignment-safe) way to implement assignment for your class is to use its swap:
myString& myString::operator=(const myString& rhs)
{
myString tmp(rhs); // invoke copy ctor
this->swap(tmp); // steal data from temp and leave it with our own old data
return *this;
} // tmp will automatically be destroyed and takes our old data with it
from = new char[stringLen+1]; should be from.stringPtr = new char[stringLen+1]; . Also remember to free the previously allocated memory before allocating new one.
Look closely at the line
from = new char[stringLen+1];
It is the same as
from = MyString(new char[stringLen+1]);
so your constructor of MyString get uninitialized array of chars. Then you trying to get the length of the string, but strlen just looping through chars of the string looking for 0 char. As we don't know what content uninitialized array of chars might have, we don't know what length strlen could return. It can even go further than array boundary and crash your program with segfault. But I can say for sure, after that there's not enough space in from.stringPtr to hold the string you want to copy in it.
So, use from.stringPtr = new char[stringLen+1]; or better from = MyString(*this); since you have copy constructor already.

Pointer Issues.. ( C++ )

Just when I thought I had it figured out, I get an exception handling error. Problem: The problem is that the private members lose the information outside of the constructor. Here's my class definition
Code:
class ClassType
{
private:
char *cPointer;
int length;
public:
ClassType();
// default constr. needed when allocating in main.
ClassType( const ClassType* );
char otherFunc();
};
classtype.cpp:
"#include ClassType.h"
ClassType( const ClassType* )
{
cPointer = ClassType->cPointer;
length = ClassType->length;
}
ClassType::ClassType( const char *myVar )
{
cPointer = new char[ strlen( myVar ) + 1 ] //+1 for trailing '\0'
strcpy( cPointer, myVar );
length = strlen( cPointer );
}
char ClassType::otherFunc()
{
cPointer; // Nothing is shown when debugging..
cPointer = "MyPointer"; // Results in acrash
length = 5; // Results in a crash
}
// The main function is working properly.
This isn't valid C++ code.
If you are using C++, shouldn't you
use std::string for the string?
Constructor based on another
instance should be ClassType(const
ClassType& rhs)
I can't think of why it would crash where you indicate, but there are several problems with your code (some of which are compile-time problems, so we can't be sure this code accurately reflects the problem):
there are ownership problems - when ClassType::ClassType( const ClassType* ) is called, which instance of ClassType owns the object pointed to by cPointer?
there's no dtor to release the memory allocated in `ClassType::ClassType( const char *myVar )'
since cPointer may point to something allocated by new or might not, you'll have issues trying to determine when the thing allocated by new should be deleted.
As far as the compile time errors go:
the definition of ClassType( const ClassType* ) should start with ClassType::ClassType( const ClassType* )
the contents of ClassType::ClassType( const ClassType* ) should be using a parameter instead of the ClassType class name as the pointer
char ClassType::otherFunc() needs a return statement
Is this the real code?
ClassType( const ClassType* )
{
cPointer = ClassType->cPointer;
length = ClassType->length;
}
If so, it needs to be like this:
ClassType( const ClassType* rhs )
{
cPointer = rhs->cPointer;
length = rhs->length;
}
Also, this constructor is not the default ctor:
ClassType( const ClassType* ); // default constr. needed when allocating in main.
A default ctor is specifically a ctor that either takes zero parameters or all the parameters have defaults specified. In other words, a default ctor is a ctor that can be called like this:
ClassType myObject;
I provided a pretty complete answer in your other question about this code. I believe that the main issue is that your copy constructor is massively broken. It will cause double free errors and other badness. Also since your destructor calls delete on the pointers you allocate, you can't ever assign string literals to your classes pointers.
Default constructors are those for which all the arguments have default values, so your constructor that takes a pointer is not a default constructor.
Your crash locations indicate the class has not been constructed properly, so you're probably getting address errors when you assign to them.
Could you post main, as that is probably key to see the problem?