【问题标题】:Add FUNCTION, LINE, time information to all existing "couts" [duplicate]将 FUNCTION、LINE、时间信息添加到所有现有的“couts”[重复]
【发布时间】:2016-01-22 17:13:29
【问题描述】:

我已经有一个使用大量 couts 的大型代码库。 我不能去改变所有现有的 couts。 我可以这样做吗,现有的 cout 添加 FUNCTIONLINE 和时间信息以及需要在 cout 中打印的内容?换句话说,我可以覆盖 cout 以使用我的实现,它将打印字符串以及所有额外信息。 我也愿意做任何其他事情,不一定要压倒一切..

也许我没有解释清楚.. 这就是我需要的。我已经有类似的东西了,

cout<<"This thing does not work";

cout<<"This thing does works but the problem is XYZ";

cout<<"There was a problem reading JHI";

。 . 等等..

在我无法编辑所有现有 couts 的大型代码库中..

我需要这些 couts 来打印类似于..的东西。

cout<<"This thing does not work"<<__FUNCTION__<<__LINE__;

cout<<"This thing does works but the problem is XYZ"<<__FUNCTION__<<__LINE__;

cout<<"There was a problem reading JHI"<<__FUNCTION__<<__LINE__;

希望这会让它更清楚.. 我希望原始 couts 自动(通过一些技巧)进行转换,以便他们也打印这些额外信息..

【问题讨论】:

  • 不,您不能覆盖cout。但是您可以将其替换为类似“my_cout”(有工具)之类的东西,这将是一个宏。
  • 对不起,你在这里不走运。我永远不会建议#defining cout
  • std::basic_ios::rdbuf。 & 下次引入对全局变量的依赖项之前考虑一下。
  • @DevSolar std::cout 是一个全局变量。你的问题到底是什么?
  • 从管理的角度来看,“我不能改变现有的 couts”与“我可以改变现有的 couts 所做的事情”并不相符。您的代码库中没有任何类似的稳定性控制吗?这是一个大量 合同违规,比您实际替换代码中的原始调用要严重得多。我不可能在代码审查中接受它。只是说。

标签: c++ function c++11 overloading overriding


【解决方案1】:

(您的问题不完全this 重复,因为您还想输出行和源文件信息,例如__FILE____LINE__,这使得显着差异;但是我觉得您的问题有点过于宽泛,缺乏细节)

自定义编译器

您可以使用GCC MELT(我已经设计和实现)自定义最近的 GCC 编译器来执行您希望执行的操作。然后,您将编写一个额外的“优化通道”,它会神奇地转换您的 std::cout << ... 输出语句(在编译器内部)添加一些 builtin expressions 通过使它们等效 std::cout << __builtin_FILE () << ' ' << __builtin_LINE () << ' ' << .....;您需要在Gimple 级别进行适当的转换。

这可能不是一项简单的任务,因为您需要了解 GCC 内部表示的细节。因此,我不完全确定它是否值得(除非您的代码库至少有 50 万行源代码行,并且花几个星期来编写您的 MELT 定制是值得的)。

如果您负担得起手动编辑每个相关行的费用,那么像 here 这样的宏方法可能更简单。

您或许可以将两者结合起来,使用 MELT 检测要编辑的正确行并将它们输入到 sed 脚本中,从而转换您的源代码以调用宏。

为什么改造不简单

在内部,编译器处理一些内部表示,这是一个规范化AST,甚至更简单的东西(Gimple)。对于 GCC,您要转换

内部表示
 extern "C" void testit(int x) {
   if (x>0)
   std::cout << "x=" << x << std::endl;
 }

进入接近

内部表示的东西
 extern "C" void transformed_testit (int x) {
   if (x>0)
     std::cout << __builtin_FILE() << ' ' << __builtin_LINE() << ' ' 
               << "x=" << x << std::endl;
 }    

为了理解 Gimple 表示,用g++ -fdump-tree-gimple 编译它们;这是第一个函数的 Gimple 代码的 textual 转储(实际上,Gimple 只是一个 in-memory 数据结构):

  void testit(int) (int x)
  {
    struct basic_ostream & D.21753;
    struct basic_ostream & D.21754;

    if (x > 0) goto <D.21751>; else goto <D.21752>;
    <D.21751>:
    D.21753 = std::operator<< <std::char_traits<char> > (&cout, "x=");
    D.21754 = std::basic_ostream<char>::operator<< (D.21753, x);
    std::basic_ostream<char>::operator<< (D.21754, endl);
    goto <D.21755>;
    <D.21752>:
    <D.21755>:
  }     

为什么需要在编译器中工作

因为您的源代码可能包含许多变体中的此类输出,包括

std::cout << "x=" << x << std::endl;

using namespace std;
cout << "x=" << x << endl;

#define MY_LOG(Out) do{std::cout<<Out<<std::endl;} while(0)
MY_LOG("x=" << x);

甚至

auto& output = std::cout;
output << "x=" << x << std::endl;

(在上面的例子中,两行代码可能相距甚远,甚至在不同的文件中,例如某些头文件中的#define MY_LOG,并在某些实现文件中使用...但是Gimple 表示在所有情况下都非常相似)

因此,纯文本或句法方法并不总是有效,您需要一个类似于编译器的复杂工具来进行转换。

因此,如果您有能力花费至少两周的时间来解决您的问题,请尝试使用 GCC MELT。否则,手动运行一些 sed 脚本,或者编写您的 Emacs 函数以进行该编辑交互式

在 C++ 中作弊

也许你有

struct myoutputat {
 const char*fil;
 int lin;
 myoutputat(const char*f, int l) : fil(f), lin(l) {};
 std::ofstream& operator << (const char*msg) { 
   std::cout << f << ' ' << l << msg;
   return std::cout;
 }
}; // end of myoutputat
#define mycout myoutputat(__FILE__,__LINE__)

那么你可能会这样做

mycout << "x=" << x << std::endl;

因此你可以在#define mycout之后尝试#define cout mycout...;它可能会溢出许多错误消息,您可以在其位置手动调整代码

PS。您可以通过私人电子邮件与我联系basile@starynkevitch.net,但请提及您的问题的 URL 并提供更多详细信息:您的代码在做什么,它的源代码大小是多少,您是什么确切的编译器使用,您的雇主和国家/地区等...

【讨论】:

  • 很高兴提到 MELT。当然完全矫枉过正,但仍然......很好。
【解决方案2】:

显而易见的解决方案是使用一些编辑器宏,例如 vim's macrosgrep -rnw 'directory' -e "cout &lt;&lt;" 配对,假设是 Linux 平台。

关于 C++,如果您在整个代码中使用 cout 而不是 std::cout,那么可能的解决方案是删除您的 using namespace std,然后推出您自己的 cout 函数- 假设您没有其他代码取决于std::,这将中断。

已标记为重复的问题,might contain an answer 您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-28
    • 1970-01-01
    • 2011-11-24
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多