2014-03-19 28 views
3

是否有任何預定義的宏來標識調用函數。預定義宏來標識調用函數?

要打印當前函數的名稱,我們使用

printf("%s", __FUNCTION__); 

一樣,如果函數調用ab控制在b,則是有辦法找出a

+6

宏在編譯時解析,並且無法知道函數調用了當前函數。在運行時,有一些環境庫可以顯示調用堆棧,如下所示:http://stackoverflow.com/a/691742/104774 – stefaanv

+1

儘管這是一個瘋狂的想法。 (1)創建一個'call stack'數組,(2)添加[function entry/exit codes](http://stackoverflow.com/questions/1472769/is-there-a-compiler-feature-to-inject-custom功能進入和退出代碼)來更新堆棧,(3)..利潤。雖然,取決於你的編譯器。 – usr2564301

+0

@Jongware(編譯器特定的)前/後函數是一個好主意,除非他們面臨同樣的問題(因爲__FUNCTION__將是那些函數,而不是調用者)。你需要一個pre/post宏,而不是通過簡單的編譯器標誌來存在。 – mah

回答

4

否。爲此,預處理器必須知道哪些函數調用了您的函數。但是,該信息當時不可用。對於(動態或靜態)庫,這些信息在編譯時實際上永遠不可用。

編輯:如@stefaanv在評論中所說的,您將不得不使用運行時方式,例如運行時由他鏈接的StackWalker庫。這是您知道什麼功能稱爲您的功能的唯一的一點。

2

您可以使用堆棧跟蹤,瞭解所有方法的流程。

void StackTrace::printStackTrace(){ 
std::cout<<"stack Trace\n"; 
std::cerr<<"stachTrace\n"; 
// storage array for stack trace address data 
void* addrlist[maxFrame+1]; 

// retrieve current stack addresses 
int addrlen = backtrace(addrlist, sizeof(addrlist)/sizeof(void*)); 
if (addrlen == 0) { 
    std::cerr<<" <empty, possibly corrupt>\n"; 
    std::cout<<" <empty, possibly corrupt\n"; 


} 
// resolve addresses into strings containing "filename(function+address)", 
// this array must be free()-ed 
char** symbollist = backtrace_symbols(addrlist, addrlen); 
// allocate string which will be filled with the demangled function name 
size_t funcnamesize = 256; 
char* funcname = (char*)malloc(funcnamesize); 
// iterate over the returned symbol lines. skip the first, it is the 
// address of this function. 
for (int i = 1; i < addrlen; i++){ 
    char *begin_name = 0, *begin_offset = 0, *end_offset = 0; 
    // find parentheses and +address offset surrounding the mangled name: 
    // ./module(function+0x15c) [0x8048a6d] 
    for (char *p = symbollist[i]; *p; ++p){ 
     if (*p == '(') 
      begin_name = p; 
     else if (*p == '+') 
      begin_offset = p; 
     else if (*p == ')' && begin_offset) { 
      end_offset = p; 
      break; 

     } 
    } 
    if (begin_name && begin_offset && end_offset 
      && begin_name < begin_offset){ 
     *begin_name++ = '\0'; 
     *begin_offset++ = '\0'; 
     *end_offset = '\0'; 
     // mangled name is now in [begin_name, begin_offset) and caller 
     // offset in [begin_offset, end_offset). now apply 
     // __cxa_demangle(): 
     int status; 
        char* ret =abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status); 
     if (status == 0) { 
      funcname = ret; // use possibly realloc()-ed string 
      //fprintf(out, " %s : %s+%s\n", 
       // symbollist[i], funcname, begin_offset); 
      std::cerr<<symbollist[ i ]<<funcname<<begin_offset<<std::endl; 
    std::cout<<symbollist[ i ] << funcname << begin_offset<<std::endl; 
     }else{ 

     //fprintf(out, " %s\n", symbollist[i]); 
      std::cerr<<symbollist[ i ]<<std::endl; 
    std::cout<<symbollist [ i ]<<std::endl; 
     } 
    } 
} 
free(funcname); 
free(symbollist); 

}

這個代碼將提供給您的理念,我從我的項目的一個複製它。

+0

這是gcc/linux特有的,對吧? – anderas

+0

@anderas ..是我只熟悉linux(g ++) – Sigstop