如何告诉 gcc 在代码的每一行调用我自己的函数来检测代码?

发布于 2024-09-28 12:53:31 字数 1919 浏览 3 评论 0 原文

例如,有源:

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number);

void func1() {
    func3();
    func4();
}

void foo() {
    func1();
    if(qqq) {
        func2();
    };
    func3();
    func4();
    for(...) {
        func5();
    }
}

它应该编译为:

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number);

void func1() {
    my_special_debugging_function("func1", "prog.c", 3);
    func3();
    my_special_debugging_function("func1", "prog.c", 4);
    func4();
    my_special_debugging_function("func1", "prog.c", 5);
}

void foo() {
    my_special_debugging_function("foo", "prog.c", 8);
    func1();
    my_special_debugging_function("foo", "prog.c", 9);
    if(qqq) {
        my_special_debugging_function("foo", "prog.c", 10);
        func2();
        my_special_debugging_function("foo", "prog.c", 11);
    };
    my_special_debugging_function("foo", "prog.c", 12);
    func3();
    my_special_debugging_function("foo", "prog.c", 13);
    func4();
    my_special_debugging_function("foo", "prog.c", 14);
    for(...) {
        my_special_debugging_function("foo", "prog.c", 15);
        func5();
        my_special_debugging_function("foo", "prog.c", 16);
    }
    my_special_debugging_function("foo", "prog.c", 17);
}

当然,my_special_debugging_function应该能够使用backtrace函数。

gcc 有选项可以做到这一点吗?或者有没有一个工具可以在源代码级别执行此操作? (例如用我的函数生成其他C源)

@lated 如何将 C/C++ 源与我的字符串“交错”(仅在适当位置的函数内)?

@lated 我应该使用什么分析器来测量_实时_时间(包括等待系统调用)花费在这个函数上,而不是_CPU_一个

For example, there is the source:

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number);

void func1() {
    func3();
    func4();
}

void foo() {
    func1();
    if(qqq) {
        func2();
    };
    func3();
    func4();
    for(...) {
        func5();
    }
}

It should compile as:

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number);

void func1() {
    my_special_debugging_function("func1", "prog.c", 3);
    func3();
    my_special_debugging_function("func1", "prog.c", 4);
    func4();
    my_special_debugging_function("func1", "prog.c", 5);
}

void foo() {
    my_special_debugging_function("foo", "prog.c", 8);
    func1();
    my_special_debugging_function("foo", "prog.c", 9);
    if(qqq) {
        my_special_debugging_function("foo", "prog.c", 10);
        func2();
        my_special_debugging_function("foo", "prog.c", 11);
    };
    my_special_debugging_function("foo", "prog.c", 12);
    func3();
    my_special_debugging_function("foo", "prog.c", 13);
    func4();
    my_special_debugging_function("foo", "prog.c", 14);
    for(...) {
        my_special_debugging_function("foo", "prog.c", 15);
        func5();
        my_special_debugging_function("foo", "prog.c", 16);
    }
    my_special_debugging_function("foo", "prog.c", 17);
}

Of course, my_special_debugging_function should be able to use backtrace function.

Is there option of gcc to do it? Or is there a tool to do it at souce code level? (e.g. generate other C souce with my function)

@related How to "interleave" C/C++ souce with my string (only inside functions at appropriate places)?

@related What profiler should I use to measure _real_ time (including waiting for syscalls) spend in this function, not _CPU_ one

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

≈。彩虹 2024-10-05 12:53:31

请参阅 GCC 文档中的 -finstrument-functions。您可能想在调试功能中使用dladdr(),这可能还需要与-Wl,-export-dynamic链接。

See -finstrument-functions in the GCC documentation. You may want to use dladdr() in the debugging function, which may also require linking with -Wl,-export-dynamic.

硬不硬你别怂 2024-10-05 12:53:31

如果您使用的 gcc 版本 >=4.5,您可以 编写一个 gcc 插件,以您喜欢的方式处理 AST。但该解决方案将依赖于编译器。

您还可以从 eclipse CDT 获取 AST 并从该输入重新生成 C 代码。

If you are using a gcc version >=4.5 you can write a gcc plugin that processes the AST in the way you like. But that solution would be compiler dependent.

You can also obtain AST from eclipse CDT and regenerate C code from that input.

还在原地等你 2024-10-05 12:53:31

正如另一个答案中所述,我认为如果没有预处理器技巧和对源代码的编辑,就没有任何方法可以告诉 GCC 这样做。 - 纳特古斯

As stated in the other answer, I don't think that there is any way to tell GCC to do that, without preprocessor tricks and edits to the source code. – nategoose

无声情话 2024-10-05 12:53:31

您可以使用aspectc++轻松完成。从 aspectc.org 获取此编译器 这是一个满足您需求的简单方面。
Trace.ah

#ifndef __trace_ah__
#define __trace_ah__
#include <cstdio>
#include <iostream>
using namespace std;
template <int I> struct ArgPrinter
{
template <class JP> static inline void work (JP &tjp) {
ArgPrinter<I - 1>::work (tjp);
cout << *tjp.template arg<I - 1> () << " ";
}
};
template <> struct ArgPrinter<0>
{
 template <class JP> static inline void work (JP &tjp) {}
};


aspect trace {
int depth=-1;
pointcut virtual methods() = "% ...::%(...)";

template <class JP> void print_args (JP &tjp)
    {
         ArgPrinter<JP::ARGS>::work (tjp);
    }

advice execution (methods()) : before ()
{
    depth++;
    cout << "Enter -> " << JoinPoint::signature() <<" Depth:"<<depth<< " ARGS " << JoinPoint::ARGS <<" (";
    tjp->arg(0);
    print_args (*tjp);
    cout<<")"<<endl;
    cout<< "console--"<<endl;
}

advice execution("% ...::%(...)" && !"void ...::%(...)") : after()
{
    cout<< "--console"<<endl;
    JoinPoint::Result res = *tjp->result();
    cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET " << res<<endl;
    depth--;
}
advice execution("void ...::%(...)") : after()
{
    cout<< "--console"<<endl;
    cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET void"<<endl;
    depth--;
}
};
#endif

使用 ac++ 编译器将此方面编译到您的项目中,然后运行您的程序。然后您应该在控制台中看到跟踪。
快乐追踪!

You can do it easily using aspectc++. Get this compiler from aspectc.org Here is a simple aspect which serves your requirements.
Trace.ah

#ifndef __trace_ah__
#define __trace_ah__
#include <cstdio>
#include <iostream>
using namespace std;
template <int I> struct ArgPrinter
{
template <class JP> static inline void work (JP &tjp) {
ArgPrinter<I - 1>::work (tjp);
cout << *tjp.template arg<I - 1> () << " ";
}
};
template <> struct ArgPrinter<0>
{
 template <class JP> static inline void work (JP &tjp) {}
};


aspect trace {
int depth=-1;
pointcut virtual methods() = "% ...::%(...)";

template <class JP> void print_args (JP &tjp)
    {
         ArgPrinter<JP::ARGS>::work (tjp);
    }

advice execution (methods()) : before ()
{
    depth++;
    cout << "Enter -> " << JoinPoint::signature() <<" Depth:"<<depth<< " ARGS " << JoinPoint::ARGS <<" (";
    tjp->arg(0);
    print_args (*tjp);
    cout<<")"<<endl;
    cout<< "console--"<<endl;
}

advice execution("% ...::%(...)" && !"void ...::%(...)") : after()
{
    cout<< "--console"<<endl;
    JoinPoint::Result res = *tjp->result();
    cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET " << res<<endl;
    depth--;
}
advice execution("void ...::%(...)") : after()
{
    cout<< "--console"<<endl;
    cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET void"<<endl;
    depth--;
}
};
#endif

Compile this aspect with your project using ac++ compiler then run your program. Then you should see the trace in the console.
Happy Tracing!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文