c – 如何检测关键函数中调用的后台函数

我正在研究非常大的c项目,它有很多实时关键功能以及很多慢速背景功能.不应从时间关键函数调用这些后台函数.那么有没有办法检测从关键函数调用的这些后台函数?编译时间会很好,但无论如何我想在这些后台函数之前检测.
更多信息,慢速和关键功能都是同一类的一部分,并共享相同的标题.

一些更多信息,关键功能在非常快的线程(> 10KHz)下运行,较慢的线程在不同的较慢线程(< = 1KHz)下运行.使用慢函数中的关键部分来保护类成员变量,因为它们都使用相同的类成员变量.这就是在关键功能调用功能的原因会降低整体系统性能.这就是为什么我喜欢自动找到所有这些功能而不是手动检查. 谢谢….

解决方法

获得Nicholas Wilson提出的编译时检测非常困难,如果不是不可能的话,但假设“背景”真的是指函数,而不是多线程(我没有提到问题中的线程,所以我认为这只是一个奇怪的措辞)你可以平凡地使用全局标志和一个更衣室对象,并断言或抛出异常.或者,输出调试消息.当然,这将仅限运行时间 – 但您应该能够非常快速地隔离违规者.调试版本的开销也很低(几乎可以保证从L1缓存运行),而且没有用于发布版本.

使用CaptureStackBackTrace,应该能够捕获违规函数的地址,像addr2line这样的工具(或者等价的MS)可以直接转换为代码中的一行.甚至可能有一个toolhelp函数可以直接进行这种翻译(虽然我不知道).

所以,这样的事情(未经测试!)可能会做到这一点:

namespace global { int slow_flag = 0; }
struct slow_func_locker
{
    slow_func_locker() { ++global::slow_flag; }
    ~slow_func_locker(){ --global::slow_flag; }
};
#indef NDEBUG
  #define REALTIME  if(global::slow_flag) \
  { \
    void* backtrace; \
    CaptureStackBackTrace(0,1,&backtrace,0); \
    printf("RT function %s called from %08x\n",__FUNCTION__,backtrace); \
  }
  #define SLOW_FUNC slow_func_locker slow_func_locker_;
#else
  #define REALTIME
  #define SLOW_FUNC
#endif

foo_class::some_realtime_function(...)
{
    REALTIME;
    //...
};

foo_class::some_slow_function(...)
{
    SLOW_FUNC;
    //...
    some_realtime_function(blah); // this will trigger
};

唯一真正的缺点(除了不是编译时)你必须用任何一个标记标记每个慢速和实时功能,但由于编译器不能神奇地知道哪个是什么,所以无论如何都没有多少选择.

请注意,全局“标志”实际上是一个计数器,而不是一个标志.原因是慢速函数可以立即调用另一个返回并清除标志的慢速函数错误地假设现在有一个快速函数(在这种情况下xgbi建议的关键部分的方法可能会死锁!).计数器可以防止这种情况发生.在存在线程的情况下,也可以用std :: atomic_int替换int.

编辑:
现在很清楚,实际上有2个线程正在运行,并且只关注其中一个(“快速”线程)不会调用“慢”函数,还有另一个简单,有效的解决方案(使用Win32 API的示例),但可以用POSIX完成任何一种方式):

当“快速”线程启动时(“慢”线程不需要这样做),将线程ID存储在某处,作为全局变量,或作为包含所有快/慢功能的对象的成员 – 在任何地方在哪里可以访问:

global::fast_thread_id = GetCurrentThreadId();

在“不受欢迎”的函数调用中拯救的宏可能看起来像:

#define CHECK_FAST_THREAD assert(GetCurrentThreadID() != global::fast_thread_id)

然后将此宏添加到任何“慢”函数中,该函数永远不应从“快速”线程调用.如果快速线程调用它不能调用函数,则断言触发并且知道调用哪个函数.

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...