SFML community forums

Help => General => Topic started by: Flawe on January 18, 2010, 02:18:02 am

Title: Overloaded global operator new
Post by: Flawe on January 18, 2010, 02:18:02 am
I've implemented my own memory management and so I've overloaded the global operator new/delete/new[]/delete[] and malloc/free/etc...

My problem is, when I create a Shape like this:

Code: [Select]
sf::Shape shape = sf::Shape::Circle( ... );

The following happens (and these are my best guesses based on the call stack):
1. sf::Shape::operator= is called with the newly create shape.
2. std::vector<sf::Shape::Point,std::allocator<sf::Shape::Point> >::operator= is called.
3. std::allocator<sf::Shape::Point>::deallocate is called, which in turn calls global operator delete.

This is were the problem hits. The global operator delete is called, which is intercepted by my implementation of the operator. That's all good, except for the fact that the pointer to be freed wasn't allocated by my operator new. I have no idea where that memory comes from and why it's not deleted with the correct method (respective to how it was allocated).

Anyway ideas what I could have missed?
Title: Re: Overloaded global operator new
Post by: Nexus on January 18, 2010, 07:51:34 pm
Quote from: "Flawe"
Anyway ideas what I could have missed?
You might have overloaded only a part of the global memory operators.

Could you show the declarations of all user-defined operators?
Title: Overloaded global operator new
Post by: Flawe on January 18, 2010, 09:38:50 pm
These are the ones I have:

Code: [Select]

INLINE void* operator new( size_t size ) throw();
INLINE void* operator new( size_t size, const std::nothrow_t& nothrow );
INLINE void* operator new[]( size_t size ) throw();
INLINE void* operator new[]( size_t size, const std::nothrow_t& nothrow  );
Title: Overloaded global operator new
Post by: Nexus on January 18, 2010, 10:57:53 pm
And where are the delete and delete[] operators? You said:
Quote from: "Flawe"
I've implemented my own memory management and so I've overloaded the global operator new/delete/new[]/delete[] and malloc/free/etc...

That's why I wrote "all" bold. ;)

By the way, do not declare functions throw() when they can throw an exception! That's lying. Better don't use exception specifications at all (I find them quite useless anyway).
Title: Overloaded global operator new
Post by: Flawe on January 18, 2010, 11:25:17 pm
I have the respective delete for each of the new above. I didn't post them as it's quite obvious what prototype they have?

The functions are defined exactly as the standard implementation provided by c++.
Title: Overloaded global operator new
Post by: Nexus on January 18, 2010, 11:36:30 pm
Okay, but I asked because you might have accidentally overloaded the wrong pairs. Nevermind, I just hope, we don't have a long discussion here, before wrong overload finally points out to be the mistake. ;)

Hm, are you really sure that the pointer wasn't allocated by your operator? Did you log pointers? Count invokations, do not only compare addresses.

I say that, because the implementation might change the exact pointer value from
Code: [Select]
delete[] ptr;to
Code: [Select]
void operator delete[](void* mem); – this means, ptr != mem. For example, for new[] and delete[], there can be additional space allocated before the actual array to hold the number of elements to destroy. Hence, the address may be offset.

What if you follow the code path with your debugger?
Title: Overloaded global operator new
Post by: Flawe on January 18, 2010, 11:43:50 pm
Here you go, here are my prototypes

Code: [Select]

INLINE void* operator new( size_t size ) throw();
INLINE void operator delete( void* ptr ) throw();
INLINE void* operator new( size_t size, const std::nothrow_t& nothrow );
INLINE void operator delete( void* ptr, const std::nothrow_t& nothrow );
INLINE void* operator new[]( size_t size ) throw();
INLINE void operator delete[]( void* ptr ) throw();
INLINE void* operator new[]( size_t size, const std::nothrow_t& nothrow );
INLINE void operator delete[]( void* ptr, const std::nothrow_t& nothrow );


I do memory tracking yes and the pointer is not allocated with my memory manager, it's from a completely different memory space. I'm working on isolating the behavior so I can step through it.
Title: Overloaded global operator new
Post by: Nexus on January 19, 2010, 10:27:38 pm
This looks okay, except of the throw() specification as stated in my upper post. Do not declare functions no-throw if they can throw! You just can't enforce that a new operator doesn't throw. Even the placement new with std::nothrow may throw, namely when the constructor raises an exception.

Make sure that everything is linked correctly. I have already encountered strange behaviour that resulted of library inconsistences. Recompile your whole project in all configurations, do the same with the used libraries if possible.

Othewise, try the usual debug tactics: Step through code, place breakpoints, reduce the problem to a minimal example.
Title: Overloaded global operator new
Post by: Flawe on January 19, 2010, 10:59:39 pm
I'd have a look at the allocators used in SFML and make sure they really are consistent with how they allocate/deallocate.
Title: Overloaded global operator new
Post by: Laurent on January 19, 2010, 11:02:32 pm
SFML (in this context) just uses a std::vector with its default allocator. In fact I think that you should be able to reproduce the problem without SFML.
Title: Overloaded global operator new
Post by: Flawe on January 19, 2010, 11:33:47 pm
Quote from: "Laurent"
SFML (in this context) just uses a std::vector with its default allocator. In fact I think that you should be able to reproduce the problem without SFML.


That's a good idea. I did a quick test and managed to create somewhat the same behavior (obviously not the exact same) but everything worked, it both allocated and deallocated using my overloads. I'll look through the SFML code and see if I can find anything.
Title: Overloaded global operator new
Post by: Laurent on January 19, 2010, 11:39:51 pm
Do you use the dynamic or static SFML libraries? Do you link your program to a shared standard library runtime or to a static one?
Title: Overloaded global operator new
Post by: Flawe on January 19, 2010, 11:43:38 pm
I'm linking to the static sfml libs. I don't understand what you mean with a shared runtime library or a static one?
Title: Overloaded global operator new
Post by: Laurent on January 19, 2010, 11:51:46 pm
The C++ standard library is... a library, and you have the choice to use it statically or dynamically. It is important that your program uses the dynamic (shared) version of the SL because SFML does so.

What EDI / compiler do you use?
Title: Overloaded global operator new
Post by: Flawe on January 19, 2010, 11:58:43 pm
Right, I'm using the dynamic runtime library with VS2008.
Title: Overloaded global operator new
Post by: Laurent on January 20, 2010, 12:02:50 am
Ok. So no problem there :D
Title: Overloaded global operator new
Post by: Flawe on January 20, 2010, 10:58:26 am
I had a quick look at the SFML code (kudos on the standard by the way, very clean!) but I couldn't see anything strange happening.

I have a call to sf::Shape::Circle that returns a Shape by value. The shape contains the std::vector with all the points, which is copied with its operator=. The problem lies with the call to deallocate() which seems to trigger my operator delete. This is because I have the following code:

Code: [Select]

class A {
    A();
    sf::Shape s;
};

A() {
    s = sf::Shape::Circle( ... );
}


The deallocate on the std::vector inside sf::Shape is called on s, since the operator= from above will have to delete the old vector which contains the point added to sf::Shape in its constructor (representing the center of the shape). The only thing I can think of is that the sf::Shape constructor is called before my operator new is linked into the translation unit, but that doesn't make sense.