Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
622 views
in Technique[技术] by (71.8m points)

gcc - Macro to replace C++ operator new

Is it possible to create macros to replace all forms of operator new with overloads that include additional args...say __FILE__ and __LINE__?

The trouble appears to be that operator new can either be coded with or without parentheses, therefore:

  • object-like macros:

    #define new new(__FILE__, __LINE__)
    

    will replace declarations like:

    A* a = new A();
    
  • and function-like macros:

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

    will replace declarations like:

    A* a = new(std::nothrow) A();
    

Unfortunately it's an error to attempt to declare two macros with the same identifier, even if they are of different types, so the following fails:

#define new new(__FILE__, __LINE__)
#define new(A) new (A, __FILE__, __LINE__) // Error: "new" already defined

Since I'm using g++ I was hopeful that employing their syntax of variadic macros would yield success, but unfortunately not. The following:

#define new(...) new(__FILE__, __LINE__, ## __VA_ARGS__)

only matches new(xyx) A(), not new A().

I know that essays have been written about why it is impossible, but I feel like I'm so close that there must be a way. Is there anything obvious that I'm missing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is what I use:

In new.cpp

const char* __file__ = "unknown";
size_t __line__ = 0;

void* operator new(size_t size) {
    void *ptr = malloc(size);
    record_alloc(ptr,__file__,__line__);
    __file__ = "unknown";
    __line__ = 0;
    return ptr;
}

void delete(void *ptr)
{
   unrecord_alloc(ptr);
   free(ptr);
}

For compactness, I'm leaving out the other definitions of new and delete. "record_alloc" and "unrecord_alloc" are functions that maintain a linked list of structure containing ptr, line, and file).

in new.hpp

extern const char* __file__;
extern size_t __line__;
#define new (__file__=__FILE__,__line__=__LINE__) && 0 ? NULL : new

For g++, "new" is expanded only once. The key is the "&& 0" which makes it false and causes the real new to be used. For example,

char *str = new char[100];

is expanded by the preprocessor to

char *str = (__file__="somefile.c",__line__=some_number) && 0 ? NULL : new char [100];

Thus file and line number are recorded and your custom new function is called.

This works for any form of new -- as long as there is a corresponding form in new.cpp


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...