加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 04:51:24 所属栏目:百科 来源:网络整理
导读:我正在研究非常大的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 %08xn",__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)

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读