Link to home
Start Free TrialLog in
Avatar of stefarg
stefarg

asked on

Problem using STL due to definition of operator new(unsigned int,void *)

Hey All,
I am working with the Darwin Streaming Server and I am trying to implement some of my own classes that need to use the STL queue libraries but there is an error occuring when use #include <queue>, as follows:

/CommonUtilitiesLib/OSMemory.h(125) : error C2084: function 'void *__cdecl operator new(unsigned int,void *)' already has a body

I have looked at this function and it is as follows:

// PLACEMENT NEW OPERATOR
inline void* operator new(size_t, void* ptr) { return ptr;}

and I assume that somewhere in the STL this function is also declared + defined.
So here's the problem, I want be able to use the STL libraries and not cause damage to the rest of the darwin code.  I tried just commenting out the function in darwin, in the hope that the implementation in the STL would be picked up but it wasn't.  (I'm fairly confident, though not certain, that the STL function and the one in darwin are identical).
Is there some #ifndef/#define type condition I could put around the funtion in the OSMemory.h file to prevent the problem or if anyone has a neat solution to this problem please reply.
This is fairly urgent,
Thanks,
Stef
Avatar of Karl Heinz Kremer
Karl Heinz Kremer
Flag of United States of America image

You may have better luck posting this in the "Macintosh Programming" area (or you may not... it's awfully quiet over there). THe best thing to do would be to post a "pointer question" in the "Mac Programming" area (e.g. a 20 point question that points to this question). Have the pointer question deleted and your points refunded once this question here is answered.
Actually, this goes this way
If u overload the operator new globally (as u have done above), then that would be used whenever memory is allocated using new operator

If u wish to have some special kind of allocation for some specific class, u could overload the new operator for the class
Thus, only objects of that class allocated thru new would use yoru version, else the default new would be used

Amit
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of stefarg
stefarg

ASKER

Hey Sys Prog,
Unfortunately making it a member method does not work, it just gives an error complaining the constructor did not expect 2 parameters,
Thanks for the suggestion though,
Stef
Avatar of stefarg

ASKER

Hey jkr,
No luck there either, just gave the errors:

c:\program files\microsoft visual studio\vc98\include\xstring(525) : warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX
        c:\program files\microsoft visual studio\vc98\include\xstring(521) : while compiling class-template member function 'void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Copy(unsigned int)'
c:\program files\microsoft visual studio\vc98\include\xmemory(34) : error C2665: 'new' : none of the 2 overloads can convert parameter 2 from type 'void *'
        c:\program files\microsoft visual studio\vc98\include\xmemory(66) : see reference to function template instantiation 'void __cdecl std::_Construct(unsigned int *,const unsigned int &)' being compiled
QTRTPFile.cpp
c:\program files\microsoft visual studio\vc98\include\xstring(525) : warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX
        c:\program files\microsoft visual studio\vc98\include\xstring(521) : while compiling class-template member function 'void __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::_Copy(unsigned int)'
c:\program files\microsoft visual studio\vc98\include\xmemory(34) : error C2665: 'new' : none of the 3 overloads can convert parameter 2 from type 'void *'
        c:\program files\microsoft visual studio\vc98\include\xmemory(66) : see reference to function template instantiation 'void __cdecl std::_Construct(unsigned int *,const unsigned int &)' being compiled

Once again, thanks for you suggestion!
Avatar of stefarg

ASKER

The only place that I can see in the code where the 'new' operator defined by darwin is used is:

char* theNewBuf = NEW char[fBufSize + sizeof(OSQueueElem)];
....
(void)new (theNewBuf) OSQueueElem(theNewBuf + sizeof(OSQueueElem));

I am quite confused regarding the syntax used here!! what are the two parameters passed here?
why is there (void) at the start, is this the void the first parameter?  Therefore would this operator overloading have a similar syntax to overload an == or < etc?
Maybe I could add an extra parameter to distinguish the 2 funtions and then just pass NULL as one of the arguements in the line above?  If this is the case, how would I alter the new function to take 3 parameters?  Is it even possible?

My last resort would be write my own queue and priority_queue classes, however I need this fairly urgently and don't really hae time to be writing them.  So if someone can post up code for an EFFICIENT queue and priority queue that doesn't use the STL (i.e. using just arrays) I will award the points to them.
I'm don't know what Darwin Streaming Server is, but ...

Wrap it's inclusion in a custom namespace. This would bring it's globally scoped items into that namespace. Hence no conflicts.

namespace Darwin
{
#include "Darwin.h" // ... whatever
}
>>stefarg
Can you post more of the code declaration, so that we can get a more complete picture.
Post the header that contians the new operator
Avatar of stefarg

ASKER

Hey there Axter,
Here's the header file:
----------------------------------OSMemory.h-------------------------------------------------------
#ifndef __OS_MEMORY_H__
#define __OS_MEMORY_H__

#include "OSHeaders.h"
#include "OSQueue.h"
#include "OSMutex.h"

class OSMemory
{
    public:
   
#if MEMORY_DEBUGGING
        //If memory debugging is on, clients can get access to data structures that give
        //memory status.
        static OSQueue* GetTagQueue() { return &sTagQueue; }
        static OSMutex* GetTagQueueMutex() { return &sMutex;    }
        static UInt32   GetAllocatedMemory() { return sAllocatedBytes; }

        static void*    DebugNew(size_t size, char* inFile, int inLine, Bool16 sizeCheck);
        static void     DebugDelete(void *mem);
        static Bool16       MemoryDebuggingTest();
        static void     ValidateMemoryQueue();

        enum
        {
            kMaxFileNameSize = 48
        };
       
        struct TagElem
        {
            OSQueueElem elem;
            char fileName[kMaxFileNameSize];
            int     line;
            UInt32 tagSize; //how big are objects of this type?
            UInt32 totMemory; //how much do they currently occupy
            UInt32 numObjects;//how many are there currently?
        };
#endif

        // Provides non-debugging behaviour for new and delete
        static void*    New(size_t inSize);
        static void     Delete(void* inMemory);

            //When memory allocation fails, the server just exits. This sets the code
        //the server exits with
        static void SetMemoryError(SInt32 inErr);
       
#if MEMORY_DEBUGGING
    private:
           
        struct MemoryDebugging
        {
            OSQueueElem elem;
            TagElem* tagElem;
            UInt32 size;
        };
        static OSQueue sMemoryQueue;
        static OSQueue sTagQueue;
        static UInt32  sAllocatedBytes;
        static OSMutex sMutex;
       
#endif
};


// NEW MACRO
// When memory debugging is on, this macro transparently uses the memory debugging
// overridden version of the new operator. When memory debugging is off, it just compiles
// down to the standard new.

#if MEMORY_DEBUGGING

#ifdef  NEW
#error Conflicting Macro "NEW"
#endif

#define NEW new (__FILE__, __LINE__)

#else

#ifdef  NEW
#error Conflicting Macro "NEW"
#endif

#define NEW new

#endif

/***********************************************************/
//HERE IS THE NEW DECLARATION OF THE OPERATOR THAT IS CAUSING ME THE
//TROUBLE.
// PLACEMENT NEW OPERATOR
inline void* operator new(size_t, char* ptr) { return ptr;}
/***********************************************************/


#if MEMORY_DEBUGGING

// These versions of the new operator with extra arguments provide memory debugging
// features.

void* operator new(size_t s, char* inFile, int inLine);
void* operator new[](size_t s, char* inFile, int inLine);

#endif

// When memory debugging is not on, these are overridden so that if new fails,
// the process will exit.
void* operator new (size_t s);
void* operator new[](size_t s);

void operator delete(void* mem);
void operator delete[](void* mem);


#endif //__OS_MEMORY_H__
--------------------------------------------------------------------------------------------------

And here is the cpp file that uses the new declaration:
-----------------------------------OSBufferPool.cpp-------------------------------------------
#include "OSBufferPool.h"
#include "OSMemory.h"

void*   OSBufferPool::Get()
{
    OSMutexLocker locker(&fMutex);
    if (fQueue.GetLength() == 0)
    {
        fTotNumBuffers++;
        char* theNewBuf = NEW char[fBufSize + sizeof(OSQueueElem)];
       
        //
        // We need to construct a Queue Element, but we don't actually need
        // to use it in this function, so to avoid a compiler warning just
        // don't assign the result to anything.
            
        (void)new (theNewBuf) OSQueueElem(theNewBuf + sizeof(OSQueueElem));

        return theNewBuf + sizeof(OSQueueElem);
    }
    return fQueue.DeQueue()->GetEnclosingObject();
}

void OSBufferPool::Put(void* inBuffer)
{
    OSMutexLocker locker(&fMutex);
    fQueue.EnQueue((OSQueueElem*)((char*)inBuffer - sizeof(OSQueueElem)));
}
--------------------------------------------------------------------------------------------------
Avatar of stefarg

ASKER

ok, based on jkr's suggestion I came up with a variation where I put #define around the function as follows:

#ifndef __PLACEMENT_NEW_INLINE
#define __PLACEMENT_NEW_INLINE
inline void* operator new(size_t, void* ptr) { return ptr;}
#endif __PLACEMENT_NEW_INLINE

and it removed the problem, (although just using it at the include did not work).
However then there was a warning appearing about exceptions:

"C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX."

But I found a solution to this at http://support.microsoft.com/default.aspx?scid=kb;en-us;q154419

So thanks for your help everyone, I think I can lay this one to rest now.
I am very grateful for all comments and suggestions,
Many thanks,
Stef