2

I am trying to auto generate a string that can be used in debug logs, the syntax I would like is:

    ClassName::FunctionName

The source code can be used on two systems with different compilers, this includes:

    Microsoft Visual Studio 2010, Version 10.0.40219.1 SP1Rel

and

    QNX Momentics, Version 4.7

I've tried this so far:

    #if defined(__FUNCDNAME__)
      #define FNAME    __FUNCDNAME__
    #elif defined(__FUNCTION__)
      #define FNAME    __FUNCTION__
    #elif defined(__FUNSIG__)
      #define FNAME    __FUNSIG__
    #elif defined(__func__)
      #define FNAME    __func__
    #elif defined(__PRETTY_FUNCTION__)
      #define FNAME    __PRETTY_FUNCTION__
    #else
      #define FNAME    ""
    #endif

I then added a bit of test code so I could see the result in the debugger:

    char szTemp[128];
    strcpy_s(szTemp, sizeof(szTemp), FNAME);

The result is not what I am after:

    ??0CLSNAME@@QAE@AAV?$SecBlock@EV?$AllocatorWithCleanup@ES0A@@@@@@0_N@Z

I have no idea what this is.

[Edit] I Changed the pre-processor's to give me a bit more visibility as to what is happening, now the code reads:

    szFrom[0] = '\0';
    #if defined(__PRETTY_FUNCTION__)
      #define FNAME    __PRETTY_FUNCTION__
      strcpy_s(szFrom, sizeof(szFrom), FNAME);
    #endif
    #if defined(__FUNCTION__)
      #define FNAME    __FUNCTION__
      strcpy_s(szFrom, sizeof(szFrom), FNAME);
    #endif
    #if defined(__FUNCDNAME__)
      #define FNAME    __FUNCDNAME__
      strcpy_s(szFrom, sizeof(szFrom), FNAME);
    #endif
    #if defined(__FUNSIG__)
      #define FNAME    __FUNSIG__
      strcpy_s(szFrom, sizeof(szFrom), FNAME);
    #endif
    #if defined(__func__)
      #define FNAME    __func__
      strcpy_s(szFrom, sizeof(szFrom), FNAME);
    #endif

When using MSVC I can see the flow and ugly output comes from FUNCDNAME which is the only condition that the flow goes into.

[Edit 2] Final working solution:

    szFrom[0] = '\0';
    #if defined(__PRETTY_FUNCTION__)
      #define FNAME    __PRETTY_FUNCTION__
      strcpy_s(szFrom, sizeof(szFrom), FNAME);
    #endif
    #if defined(__FUNCTION__)
      #define FNAME    __FUNCTION__
      strcpy_s(szFrom, sizeof(szFrom), FNAME);
    #endif
    #if defined(__FUNSIG__)
      #define FNAME    __FUNSIG__
      strcpy_s(szFrom, sizeof(szFrom), FNAME);
    #endif
    #if defined(__func__)
      #define FNAME    __func__
      strcpy_s(szFrom, sizeof(szFrom), FNAME);
    #endif

On MSVC this gives the output:

    ClassName::FunctionName

Thanks go to P.W.

SPlatten
  • 5,334
  • 11
  • 57
  • 128
  • OT, but given that you're apparently trying to write portable code, I'd avoid any of the Annex K `*_s()` functions such as `strcpy_s()`. Per http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm: *A widespread fallacy originated by Microsoft's deprecation of the standard functions [DEPR] in an effort to increase the adoption of the APIs is that every call to the standard functions is necessarily unsafe and should be replaced by one to the "safer" API* – Andrew Henle Nov 20 '18 at 12:02
  • See https://stackoverflow.com/questions/7008485/func-or-function-or-manual-const-char-id – sergiopm Nov 20 '18 at 12:03
  • (cont) and *Microsoft Visual Studio implements an early version of the APIs. However, the implementation is incomplete and conforms neither to C11 nor to the original TR 24731-1. ... As a result of the numerous deviations from the specification the Microsoft implementation cannot be considered conforming or portable.* – Andrew Henle Nov 20 '18 at 12:03
  • 1
    The result you've given is on VS or QNX? It would help if you can post the result on both the platforms. – iVoid Nov 20 '18 at 12:04
  • 1
    I'd also rearrange the order to use `__PRETTY_FUNCTION__` first to hopefully get the demangled name, then the standards-compliant `__func__`, *then* the others. See https://stackoverflow.com/questions/4384765/whats-the-difference-between-pretty-function-function-func But you should also try emitting all of them to see which one suits your needs bast. The problem may be that `__func__` is not necessarily a macro. – Andrew Henle Nov 20 '18 at 12:05
  • @iVoid, the result was when running with MSVC – SPlatten Nov 20 '18 at 12:38
  • @SPlatten Those defines have different values, so you should put the most desirable one first. Some might give "ClassName::FunctionName", some "FunctionName", some "void ClassName::FunctionName(int)", etc. – VLL Nov 20 '18 at 12:40
  • @Ville-Valtteri, can you suggest a better order? – SPlatten Nov 20 '18 at 12:42
  • @SPlatten The values depend on the compiler, because they are not in standard. You only have two compilers, so print values of each one and see what they look like. – VLL Nov 20 '18 at 12:44

2 Answers2

2

If you want to print in the format ClassName::FunctionName in Visual Studio, __FUNCTION__ is the most suitable. So you will have to put it first in your hierarchy of conditional inclusions (#ifdefs).

#if defined(__FUNCTION__)
    #define FNAME    __FUNCTION__
...
...
#else
    #define FNAME    ""
#endif

You can see it live here.

P.W
  • 26,289
  • 6
  • 39
  • 76
0

Which you is called decorated name. The name decorations c++ specific thing. It is need for the linker, which except unique names. But In c++ the two or more function can have same name. This is calling function overloading.

Example:

class
{
    void Function()
    void Function( int i )
    void Function( string s)
}

this is valid code. So the compiler decorated the function names, based on the parameter list and the contains class name. So we give the unique name after the decoration mechanism.

here is an article: https://msdn.microsoft.com/en-us/library/56h2zst2.aspx

György Gulyás
  • 1,290
  • 11
  • 37