c - 使用字符串表 "decoder ring"的 printf() 调试库

标签 c debugging printf string-table

我写信是想看看你们中是否有人见过或听说过我将要描述的想法的实现。

我有兴趣为嵌入式目标开发一个 printf 风格的调试库。目标非常遥远,我和目标之间的通信带宽预算非常紧张,所以我希望能够以非常有效的格式获取调试消息。

调试语句通常如下所示:

myDebugLibraryPrintf("Inside loop, processing item %d out of %d.\n", i, numItems);

当然,当它扩展为文本时,打印的字符串类似于“Inside loop, processing item 5 out of 10.\n”,总共约 42 个字节。这条语句打印出的超过 90% 的数据是静态的、文字的——在编译时已知。当然,只有“5”和“10”在编译时是未知的。

我想要做的是能够只发回这两个整数(8 个字节而不是 42 个)。一旦我收到该数据,我就会有某种“解码器环”,让我“重构”接收到的数据并在我的位置打印出完整的调试消息。

我会通过自动(作为构建过程的一部分)在编译时为每个 myDebugLibraryPrintf() 语句提供一个唯一 ID,并生成一个将这些唯一 ID 映射到原始格式字符串的表来生成“解码器环”。然后,任何时候在目标上调用 myDebugLibraryPrintf() 时,它都会传输唯一 ID 和任何 "%d""%f" 等可变参数值在格式字符串中看到,但不传输格式字符串本身。 (我现在可能只是不允许 "%s" 项目...)回到我的位置,我们将有一个程序来查找表中的唯一 ID,找到合适的格式字符串,并使用它来重建原始调试消息。

我觉得以前可能有人有过这个想法,我想社区中可能有人会看到类似的东西(或者甚至知道一个开源库可以做到这一点)。

约束:

  • 澄清一下,我在这里处理 C/C++,我对 printf() 的 100% 完整替换实现不感兴趣——比如非文字格式字符串,不需要支持 %s(字符串)格式说明符或更高级的格式说明符,例如将宽度或精度放入带有 %*.*d 的可变参数列表中。

  • 我希望字符串表作为构建过程的一部分自动生成,这样添加调试就不会比添加传统的 printf() 涉及更多工作。如果需要的工作量超过最低限度,我的项目中就没有人会使用它。

  • 在生成字符串表的构建过程中做额外的工作几乎是假设的。幸运的是,我可以控制所有我有兴趣使用这个库的源代码,而且我在构建过程中有很大的灵 active 。

谢谢!

最佳答案

我只见过用一组预定义的字符串实现这个想法。代码看起来像 debug_print(INSIDE_LOOP_MSG_ID, i, n)。当开发人员想要添加新消息时,他们必须将新文本放入特定的头文件中并为其指定一个新 ID。

我认为从看起来很正常的打印语句动态生成它的想法是一个有趣的挑战。我还没有遇到任何现有的实现。

一个想法可能是将第一个字符串参数转换为 hash value at compile time 的宏/模板.因此,开发人员编写了 debug_print("test %d",i),它被编译为 debug_port_send(0x1d3s, i)。编写一个后处理脚本来提取字符串和哈希值以供接收方使用应该很简单。 (解决哈希冲突的最简单方法是提供错误消息并强制用户稍微更改措辞)。

编辑:
所以我在上面的链接中使用编译时散列进行了尝试。

#define QQuot_(x) #x
#define QQuote(x) QQuot_(x)
#define Debug_Print(s, v) (Send( CONSTHASH(QQuote(__LINE__)##s), *((long*)&(v))))

void Send(long hash, long value)
{
   printf("Sending %x %x\n", hash, value); //replace with COMMS
}


int main()
{
   int i = 1;
   float f= 3.14f;
   Debug_Print("This is a test %d", i);
   i++;
   Debug_Print("This is a test %d", i);
   Debug_Print("This was test %f", f);
}

只要稍微聪明一点,您就可以支持多个参数。 检查 dissassembly 表明所有哈希值确实是在编译时计算的。输出符合预期,没有来自相同字符串的冲突。 (This page 确认十六进制对于 3.14 是正确的):

Sending 94b7555c 1
Sending 62fce13e 2
Sending 506e9a0c 4048f5c3

您现在所需要的只是一个文本处理脚本,该脚本可以在从 Debug_Print 中提取字符串的代码上运行,计算哈希值并在您的接收端填充一个表。接收者从 Send 调用中获取哈希值,查找随附的字符串,并将其与参数一起传递给普通的 printf 调用。

我看到的唯一问题是编译时哈希中的嵌套宏是 confusing my refactoring plug-in and killing my IDE responsiveness .禁用加载项消除了该问题。

关于c - 使用字符串表 "decoder ring"的 printf() 调试库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6912406/

相关文章:

c - 在c函数中传递指针值的问题

html - 通过套接字下载 HTTP (C)

C++:派生类对象被析构时释放动态内存

c++ - 如果我在代码的 printf 部分中使用 %s 而不是 %c,代码背后的解释

c - 函数如何返回指向堆分配对象的指针

c - c 中的表达式为真返回 1

c++ - Windows 调试器上的 VS Code 无法与 freopen 一起使用

javascript - 使用 Visual Studio Code 调试 Chrome 扩展

c - newlib printf 函数错误

c++ - "printf"字符串打印乱码