You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++可变参数测试输出宏线程安全及实现问题咨询

C++可变参数调试输出宏相关问题

我编写了一组专用于测试输出场景的C++可变参数输出宏,输出格式为:函数名@文件名(首尾字符) 行号 变量名=值,示例如下:

L(i,b); // 输出示例:{evenRCpower@ih2943: i=36 b=1  @}
L(hex,pd,dec,check.back(),even,"e.g."); 
  // 输出示例:{way@ih3012:  pd=babbbaba  check.back()=15216868001 even=1 e.g.  @}

目前该宏可在g++ C17实验版本(g1z)、C++17标准环境下正常运行,仅存在少量使用限制:逗号、输出格式指定符的使用受限,可通过增强文本分析逻辑放宽限制。现有以下技术疑问:

  1. 核心问题:如何实现该宏的完全线程安全?
  2. 是否存在无需文本分析的实现方案?例如可避免使用#__VA_ARGS__、直接拆分获取每个传入参数名称的方案?
  3. 如何准确区分传入的普通参数与输出流操作符(该功能为必要需求)?
  4. 若要适配其他更新版本的C标准与g编译器,需要对现有代码做哪些修改?
  5. 即便通过本地定义的输出流将单行完整内容先写入本地字符串,也无法完全解决并行场景下输出内容混杂的问题,该现象的成因是什么?哪个C++版本会从标准层面解决该问题?

下方给出基于std::cout实现的简化基础版本代码,该版本单线程运行正常,但多线程并行场景下会出现输出错乱问题:

#define WO_IS 1
#define L(...) locate(__FILE__,__LINE__,__func__,"\n{",": "," @}\n",#__VA_ARGS__,##__VA_ARGS__)

string argTExcludes = " hex dec std::hex std::dec ", funcExcludes = " setprecision ";

string argT(const string sarg,int &nextpos) { // 未实现精确文本分析!仅支持简单字符串、字符类型参数,传入带逗号的参数(如f(x,y,"A,",','))时会出现异常输出
  int i = nextpos+1, pos = i, follow = 0; string nom; bool apo = false; 
  for (; i < sarg.size(); i++) 
    if(sarg.at(i) == ' ') {
      // 跳过空格
    } else if ((sarg.at(i) == ',')||(i == (sarg.size()-1))) { 
      nom = sarg.substr(pos,i-pos);
      if (argTExcludes.find(nom) != std::string::npos) { nextpos = i; return ""; };
      break;
    } else {
      if ((sarg.at(i) != ' ') && (!follow++) && ((sarg.at(i) == '"')||(sarg.at(i) == '\'')) ) apo = true; 
      if ((sarg.at(i) == '"') && ( (i==0)||((i > 0) && (sarg.at(i-1) != '\'')) )) { i++; while ((sarg.at(i) != '"') && (i < sarg.size())) i++; };
      if (sarg.at(i) == '(') { 
        nom = sarg.substr(pos,i-pos); if (funcExcludes.find(nom) != std::string::npos) apo = true; 
      };
    };
  nextpos = i;
  return (apo)?"":sarg.substr(pos,i-pos)+"=";
};

template <typename... Ts>
inline void locate(string ort,long line,string funct,const string prefix, const string trenner, const string postfix, string sarg, Ts... args) 
{ 
#if WO_IS > 0 // 已取消所有范围限制
    int pos = -1; bool apo; sarg += ",";
    std::ios_base::fmtflags f( cout.flags() );
    std::cout << prefix << funct << '@' << ort[0] << ort.back() << dec << line << trenner; 
    cout.flags( f );
    ((std::cout << argT(sarg,pos) << args << ' '), ...); // 禁止传入endl,即使参数末尾不加空格也会触发语法错误
    // ((std::cout << argT(sarg,pos); std::cout << args; std::cout << ' '), ...); // 该写法下传入endl同样会触发语法错误
    if (postfix == "\0") std::cout.flush();
    else std::cout << postfix;
#endif
};

内容的提问来源于stack exchange,提问作者user19365174

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 12:18:18