Nasıl çağıran işlevin adını buluyorsunuz?

oy
34

Ne var ki ben bazı fonksiyonları reimplemented ve işlevleri onları aradığınız olduğunu öğrenmek istiyorum, çıkış akım fonksiyonu ismi PRETTY_FUNCTION kullanıyoruz.

C ++ nasıl arama rutin işlev adı alabilirim?

Oluştur 09/12/2008 saat 16:43
kaynak kullanıcı
Diğer dillerde...                            


9 cevaplar

oy
17

Bunun için iki seçeneğe:

  1. Tam bir stacktrace olsun (isim, modül dahil ve arama fonksiyonu ofset) ile glibc'nin son sürümleri ile yapabilirsiniz GNU backtrace fonksiyonları . Bkz burada cevabımı detayları için. Bu muhtemelen en kolay şeydir.

  2. Bu tam olarak aradığınız gibi değilse, o zaman deneyebilirsiniz libunwind , ancak daha fazla iş dahil olacak.

Bu size (PRETTY_FUNCTION olduğu gibi) statik bilmek bir şey değildir unutmayın; aslında işlev seni aradı anlamaya yığını yürümek zorunda. Yani bu sıradan ayıklama printfs yapıyor gerçekten değer bir şey değildir. Eğer daha ciddi hata ayıklama veya analiz yapmak isterseniz, yine de, o zaman bu sizin için faydalı olabilir.

Cevap 09/12/2008 saat 16:50
kaynak kullanıcı

oy
0

Muhtemelen potansiyel onları diyebiliriz tüm fonksiyonların isimleri istiyorum. Bu, temel olarak çağrı grafikte kenarları bir kümesidir. Doxygen çağrısı grafik üretebilir ve daha sonra da fonksiyonları düğümün gelen kenarlarına bakarak meselesi basitçe bu.

Cevap 09/12/2008 saat 16:54
kaynak kullanıcı

oy
0

köknar yaklaşım olarak, sadece işlev isimleri için kodların grep. Daha sonra Doxygen ve daha sonra dinamik günlük (her ikisi de başkaları tarafından ele alınmıştır) gelir.

Cevap 09/12/2008 saat 17:18
kaynak kullanıcı

oy
39

Burada sık sık kullanabileceğiniz bir çözümdür. Fiili fonksiyon koduna hiçbir değişiklik gerektirmeden avantajına sahiptir ( , işlevlerini stackwalk için hiçbir ekleme çağrıları işlev adlarında iletilecek parametreleri değiştirme veya ekstra kütüphanelere bağlama. ). Çalıştırmak için tek yapmanız gereken önişlemci sihirli bir bit kullanmak gerekir:

Basit Örnek

// orignal function name was 'FunctionName'
void FunctionNameReal(...)
{
  // Do Something
}

#undef FunctionName
#define FunctionName printf("Calling FunctionName from %s\n",__FUNCTION__);FunctionNameReal

Geçici olarak işlevini yeniden adlandırmak, ancak daha fazla öneriler için aşağıdaki nota görmek gerekir. Bu neden olacaktır printf()işlevini çağırarak her noktadaki açıklamada. Açıkçası, bir üye işlevini çağırarak eğer bazı düzenlemeleri yapabilir ya da (dönüş değerini yakalamak için gereken zorunda gibi işlev çağrısını geçmek ve __FUNCTION__ ... aynı tür döndüren bir özel işlevine ), ancak temel bir tekniktir aynı. Sen kullanmak isteyebilirsiniz __LINE__ve __FILE__sahip olduğunuz derleyici bağlı diğer bazı önişlemci makroları veya. (Bu örnek, MS VC ++ için özel olduğunu, ancak muhtemelen diğerlerinde çalışır.)

Ayrıca, çevrili Başlığınızda böyle bir şey koymak isteyebilirsiniz #ifdefsizin için de gerçek fonksiyonunu yeniden adlandırma işleyebilir koşullu açmak için korumaları.

UPDATE [2012-06-21]

Cevabımı genişletmek için bir istek aldık. Sonradan anlaşıldı ki, benim yukarıdaki örnek biraz basit bir yaklaşım. İşte C ++ kullanarak, bu işleme bazıları tamamen derleme örneklerdir.

Bir dönüş değeri ile tam Kaynak Örneği

Bir kullanma classile operator()bu oldukça yalındır yapar. Bu, ilk teknik ile ve dönüş değerleri olmadan fonksiyonlarını müstakil için çalışır. operator()Sadece söz konusu işleviyle aynı getiriyi yansıtır ve eşleşen argümanlar sahip olması gerekir.

Sen ile bu derleme yapabilirsiniz g++ -o test test.cppolmayan bir raporlama versiyonu için ve g++ -o test test.cpp -DREPORTarayanın bilgileri görüntüleyen bir sürümü için.

#include <iostream>

int FunctionName(int one, int two)
{
  static int calls=0;
  return (++calls+one)*two;
}

#ifdef REPORT
  // class to capture the caller and print it.  
  class Reporter
  {
    public:
      Reporter(std::string Caller, std::string File, int Line)
        : caller_(Caller)
        , file_(File)
        , line_(Line)
      {}

      int operator()(int one, int two)
      {
        std::cout
          << "Reporter: FunctionName() is being called by "
          << caller_ << "() in " << file_ << ":" << line_ << std::endl;
        // can use the original name here, as it is still defined
        return FunctionName(one,two);
      }
    private:
      std::string   caller_;
      std::string   file_;
      int           line_;

  };

// remove the symbol for the function, then define a new version that instead
// creates a stack temporary instance of Reporter initialized with the caller
#  undef FunctionName
#  define FunctionName Reporter(__FUNCTION__,__FILE__,__LINE__)
#endif


void Caller1()
{
  int val = FunctionName(7,9);  // <-- works for captured return value
  std::cout << "Mystery Function got " << val << std::endl;
}

void Caller2()
{
  // Works for inline as well.
  std::cout << "Mystery Function got " << FunctionName(11,13) << std::endl;
}

int main(int argc, char** argv)
{
  Caller1();
  Caller2();
  return 0;
}

Örnek çıktı (Raporlama)

Reporter: FunctionName() is being called by Caller1() in test.cpp:44
Mystery Function got 72
Reporter: FunctionName() is being called by Caller2() in test.cpp:51
Mystery Function got 169

Temel olarak, her yerde o FunctionNameoluşur, bu değiştirir Reporter(__FUNCTION__,__FILE__,__LINE__)net etkisi hemen bir çağrı ile bazı nesne örneklemesini yazma önişlemci olduğunu operator()fonksiyonu. Sen ile önişlemci değiştirmelerin (GCC olarak) sonucu görebilirsiniz g++ -E -DREPORT test.cpp. Caller2 () bu olur:

void Caller2()
{
  std::cout << "Mystery Function got " << Reporter(__FUNCTION__,"test.cpp",51)(11,13) << std::endl;
}

Bunu görebilirsiniz __LINE__ve __FILE__ikame edilmiş. (Neden emin değilim __FUNCTION__hala dürüst olmak gerekirse çıktıda gösterir ama derlenmiş sürümü sağ işlevini bildirir, bu yüzden muhtemelen çok geçişli Ön işlem veya bir gcc hata ile ilgili bir şey vardır.)

Sınıf üye işlevi ile tam Kaynak Örneği

Bu biraz daha karmaşık, ama önceki örneğe çok benzer. Yerine sadece işlevine çağrı değiştirme, biz de sınıf yerini almaktadır.

Yukarıdaki örnekte olduğu gibi, bu derleme yapabilirsiniz g++ -o test test.cppolmayan bir raporlama versiyonu için ve g++ -o test test.cpp -DREPORTarayanın bilgileri görüntüleyen bir sürümü için.

#include <iostream>

class ClassName
{
  public:
    explicit ClassName(int Member)
      : member_(Member)
      {}

    int FunctionName(int one, int two)
    {
      return (++member_+one)*two;
    }

  private:
    int member_;
};

#ifdef REPORT
  // class to capture the caller and print it.  
  class ClassNameDecorator
  {
    public:
      ClassNameDecorator( int Member)
        : className_(Member)
      {}

      ClassNameDecorator& FunctionName(std::string Caller, std::string File, int Line)
      {
        std::cout
          << "Reporter: ClassName::FunctionName() is being called by "
          << Caller << "() in " << File << ":" << Line << std::endl;
        return *this;
      }
      int operator()(int one, int two)
      {
        return className_.FunctionName(one,two);
      }
    private:
      ClassName className_;
  };


// remove the symbol for the function, then define a new version that instead
// creates a stack temporary instance of ClassNameDecorator.
// FunctionName is then replaced with a version that takes the caller information
// and uses Method Chaining to allow operator() to be invoked with the original
// parameters.
#  undef ClassName
#  define ClassName ClassNameDecorator
#  undef FunctionName
#  define FunctionName FunctionName(__FUNCTION__,__FILE__,__LINE__)
#endif


void Caller1()
{
  ClassName foo(21);
  int val = foo.FunctionName(7,9);  // <-- works for captured return value
  std::cout << "Mystery Function got " << val << std::endl;
}

void Caller2()
{
  ClassName foo(42);
  // Works for inline as well.
  std::cout << "Mystery Function got " << foo.FunctionName(11,13) << std::endl;
}

int main(int argc, char** argv)
{
  Caller1();
  Caller2();
  return 0;
}

İşte örnek çıktı:

Reporter: ClassName::FunctionName() is being called by Caller1() in test.cpp:56
Mystery Function got 261
Reporter: ClassName::FunctionName() is being called by Caller2() in test.cpp:64
Mystery Function got 702

Bu sürümün yüksek noktaları orijinal sınıf süsleyen bir sınıf ve izin, sınıf örneği başvurusunu döndüren bir yedek fonksiyonu olan operator()gerçek işlev çağrısı yapmak.

O birisi yardım umuyoruz!

Cevap 18/12/2008 saat 16:22
kaynak kullanıcı

oy
2

Açıkça sorulan daha soruya daha olmadığı sürece, sadece işlevini yeniden adlandırmak ve denir nerede derleyici / bağlayıcı söyleyeyim.

Cevap 21/06/2012 saat 18:48
kaynak kullanıcı

oy
8

GCC sürümü ≥ 4.8 ile kullanabilirsiniz __builtin_FUNCTION- değil karıştırılmamalıdır olmak __FUNCTION__ve benzeri - biraz belirsiz gibi görünüyor.

Örnek:

#include <cstdio>

void foobar(const char* str = __builtin_FUNCTION()){
    std::printf("called by %s\n", str);
}

int main(){
    foobar();
    return 0;
}

çıktı:

called by main

WandBox ile Örnek

Cevap 15/05/2017 saat 02:30
kaynak kullanıcı

oy
0

Eğer programda son n noktalarında kontrolden lokusları izlemek için bu kodu kullanabilirsiniz. Kullanımı: Aşağıda ana işlevine bakın.

// What: Track last few lines in loci of control, gpl/moshahmed_at_gmail
// Test: gcc -Wall -g -lm -std=c11 track.c
#include <stdio.h>
#include <string.h>

#define _DEBUG
#ifdef _DEBUG
#define lsize 255 /* const int lsize=255; -- C++ */
struct locs {
  int   line[lsize];
  char *file[lsize];
  char *func[lsize];
  int  cur; /* cur=0; C++ */
} locs;

#define track do {\
      locs.line[locs.cur]=__LINE__ ;\
      locs.file[locs.cur]=(char*)__FILE__ ;\
      locs.func[locs.cur]=(char*) __builtin_FUNCTION() /* __PRETTY_FUNCTION__ -- C++ */ ;\
      locs.cur=(locs.cur+1) % lsize;\
  } while(0);

void track_start(){
  memset(&locs,0, sizeof locs);
}

void track_print(){
  int i, k;
  for (i=0; i<lsize; i++){
    k = (locs.cur+i) % lsize;
    if (locs.file[k]){
      fprintf(stderr,"%d: %s:%d %s\n",
        k, locs.file[k],
        locs.line[k], locs.func[k]);
    }
  }
}
#else
#define track       do {} while(0)
#define track_start() (void)0
#define track_print() (void)0
#endif


// Sample usage.
void bar(){ track ; }
void foo(){ track ; bar(); }

int main(){
  int k;
  track_start();
  for (k=0;k<2;k++)
    foo();
  track;
  track_print();
  return 0;
} 
Cevap 22/05/2018 saat 00:34
kaynak kullanıcı

oy
2

Varyasyon Aaron cevap. Bu cevap bu sorunu olup olmadığını emin değilim, ama bir yaptığınızda #define functionproje aynı üye sınıf fonksiyon adıyla çeşitli sınıfları varsa, o zaman, bir genel değişken olur bütün sınıflar kendi işlev adı aynı şekilde yeniden tanımlanmıştır sahip olacak işlevi.

#include <iostream>

struct ClassName {
    int member;
    ClassName(int member) : member(member) { }

    int secretFunctionName(
              int one, int two, const char* caller, const char* file, int line) 
    {
        std::cout << "Reporter: ClassName::function_name() is being called by "
                << caller << "() in " << file << ":" << line << std::endl;

        return (++member+one)*two;
    }
};

#define unique_global_function_name(first, second) \
        secretFunctionName(first, second, __FUNCTION__,__FILE__,__LINE__)

void caller1() {
    ClassName foo(21);
    int val = foo.unique_global_function_name(7, 9);
    std::cout << "Mystery Function got " << val << std::endl;
}

void caller2() {
    ClassName foo(42);
    int val = foo.unique_global_function_name(11, 13);
    std::cout << "Mystery Function got " << val << std::endl;
}

int main(int argc, char** argv) {
    caller1();
    caller2();
    return 0;
}

Sonuç:

Reporter: ClassName::function_name() is being called by caller1() in D:\test.cpp:26
Mystery Function got 261
Reporter: ClassName::function_name() is being called by caller2() in D:\test.cpp:33
Mystery Function got 702
Cevap 17/11/2018 saat 16:13
kaynak kullanıcı

oy
-2

Cflow C / C ++ olarak yazılmış kaynak kodu çağrısı grafik elde etmek için kullanılabilir. Ne istediğini almak için bu çağrı grafiği ayrıştırabilir.

Cevap 23/07/2019 saat 17:17
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more