Thread: Macro has same name as Function?

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    4

    Macro has same name as Function?

    Hi all,
    I'm analysing memwatch, a memory leaks detector, and came across this macro

    Code:
    #define malloc(n)       mwMalloc(n,__FILE__,__LINE__)
    And then in function mwMalloc, it calls malloc again....

    Code:
    void* mwMalloc( size_t size, const char* file, int line) {
       .....
    
        mw = (mwData*) malloc( needed );
       .....
    }
    Can anyone please enlighten me how is this possible?? How does

    Code:
        mw = (mwData*) malloc( needed );
    know that it's calling a function, not the defined macro??

    Thanks in advance.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    1. Put your malloc/free wrappers in a separate source file, away from the scope of the macro which replaces it.

    2. Or try this, put ( ) around the function name.
    mw = (malloc)( needed );

    Also, there is no need to cast the return result of malloc in C, see the FAQ.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Can anyone please enlighten me how is this possible??
    If the macro is defined, any calls to malloc will be textually replaced with mwMalloc at preprocessing time. That happens before the code is compiled and function calls are converted into relative addresses, so mwMalloc will actually be called instead of malloc. Technically, this practice is dicey at best because you're not supposed to redefine a standard name, but in practice it generally works.
    My best code is written with the delete key.

  4. #4
    Registered User
    Join Date
    Sep 2007
    Posts
    4
    Quote Originally Posted by Prelude View Post
    >
    If the macro is defined, any calls to malloc will be textually replaced with mwMalloc at preprocessing time. That happens before the code is compiled and function calls are converted into relative addresses, so mwMalloc will actually be called instead of malloc.
    If I understand it right, Prelude, at preprocessing time, if it replaces *any* calls to malloc, then the code will be something like this, before compiling...

    Code:
    void* mwMalloc( size_t size, const char* file, int line) {
       .....
    
        /* in stead of     mw = (mwData*) malloc( needed );*/
       /* Now it is */
        mw = (mwData*) mwmalloc( needed, __FILE__, __LINE__ );
       .....
    }
    then isn't looping infinitely??? Still my question that how does the compiler know which call is a macro or which is the function, when they look exactly the same.

    Salem mentioned something about the scope of the macro, but the macro is defined in memwatch.h and memwatch.c implements the function....

    I'm lost...

  5. #5
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by coolclu3 View Post
    I'm lost...
    Basically, the preprocessor goes through your code and finds all the calls to malloc, *after* the macro has been defined. It then goes away and for each of those substitutes malloc with the function call. Once it has replaced all the calls it found originally, it stops. That's how the recursion breaks.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  6. #6
    Registered User
    Join Date
    Sep 2007
    Posts
    4
    Thanks but sorry I still don't get you QuantumPete.
    The only steps that i can imagine this possible is something like this, when compiling:

    1. Get all the #define (s)
    2. Define malloc by compiling and translate mwMalloc() to assembly or whatver, then store it somewhere in memory. This function will call the "real" C malloc
    3. Preprocessing: replaces all the malloc() calls with mwMalloc, *excluding* the call inside the definition of mwMalloc() (since it is already compiled).
    4. Compile: Linking the mwMalloc() to the already assigned assembly or something...

    Other than that, I don't see how the loop can break if mwMalloc calls itself...

    More explanation please?

  7. #7
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by coolclu3 View Post
    More explanation please?
    certainly. The prime thing you have to remember about the preprocessor is:
    (drum roll)
    It's a text substitution system *only*
    The preprocessor will not do *any* compilation whatsoever. Consider this code:
    Code:
    #define MAX_CHAR 6
    int main () {
        char my_name[MAX_CHAR] = "Peter"
        printf ("My name is: %s\n", my_name);
    }
    I've ommited the standard headers that you need for printf.
    The Preprocessor runs and sees the #define, which tells it to take all instances in the code of MAX_CHAR and replace them with 6. Nothing else, this is important, there's no type checkin, no syntax checking and no compilation, all that is done by the compiler. Once the preprocessor is done, your code will look something like this:
    Code:
    int main () {
        char my_name[6] = "Peter"
        printf ("My name is: %s\n", my_name);
    }
    Same with your function macro. It's a pure text based replacement.

    Any clearer?

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    mwMalloc() calling itself is just infinite recursion, and something you don't want.

    > but the macro is defined in memwatch.h and memwatch.c implements the function....
    Except everything else needs to see the macro, and your wrapper function doesn't.
    If it does, then you end up with the wrapper calling the wrapper.

    Did you try the parentheses trick?

    You could also add
    #undef malloc
    right after you have included memwatch.h in memwatch.c
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I've written almost identical code (major difference was the name of my wrapper malloc function). The principile is this:
    In the implementation file where mwMalloc() is defined, you do NOT have a macro to replace malloc() with mwMalloc() . Let's call this file mwMalloc.c for simplicity.
    In all OTHER files, the macro should be present, so that all other calls to malloc are replaced with mwMalloc.

    There are several ways to achieve this, the simplest two are:
    1. Do not include the header file that gives
    Code:
    #define malloc... mwMalloc...
    in the mwMalloc.c
    2. Do something like:
    Code:
    // mwMalloc.c:
    #define MW_INTERNAL  1
    ... 
    #include "mwMalloc.h"
    ... 
    
    
    // mwMalloc.h:
    ...
    #if !MW_INTERNAL
    #define malloc(n) mwMalloc(...)
    #define free(p) mwFree(...)
    #endif
    If I remember right, I used the latter method.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Registered User
    Join Date
    Sep 2007
    Posts
    4
    Quote Originally Posted by matsp View Post
    Code:
    // mwMalloc.c:
    #define MW_INTERNAL  1
    ... 
    #include "mwMalloc.h"
    ... 
    
    
    // mwMalloc.h:
    ...
    #if !MW_INTERNAL
    #define malloc(n) mwMalloc(...)
    #define free(p) mwFree(...)
    #endif
    If I remember right, I used the latter method.

    --
    Mats
    matsp, Salem, you ROCK!! Thanks a lot!!! This is exactly what memwatch is doing.

    Guys,thank you all!, Mistery resolved
    Btw, if you're checking memory leaks in your apps, memwatch is pretty good i guess.

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by coolclu3 View Post
    matsp, Salem, you ROCK!! Thanks a lot!!! This is exactly what memwatch is doing.

    Guys,thank you all!, Mistery resolved
    Btw, if you're checking memory leaks in your apps, memwatch is pretty good i guess.
    I can't judge that, but for obvious types of memory leaks and other "misuse of malloc/free" the technique of replacing malloc is a good starting position - it is then up to the logic inside these "wrapper" functions if it's doing what you need or not. Detecting memory leaks is one thing that can be useful with this, another is detecting writes outside the allocated memory (by adding a "buffer zone" before/after the allocated memory), as well as detecting double free and such.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. doubt in c parser coding
    By akshara.sinha in forum C Programming
    Replies: 4
    Last Post: 12-23-2007, 01:49 PM
  2. Troubleshooting Input Function
    By SiliconHobo in forum C Programming
    Replies: 14
    Last Post: 12-05-2007, 07:18 AM
  3. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  4. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  5. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM