jer*_*ble 8 c debugging printf string-table
我正在写信,看看你们中是否有人见过或听说过我将要描述的想法的实现.
我有兴趣为嵌入式目标开发一个printf样式的调试库.目标是非常远程的,我和目标之间的通信带宽预算非常紧张,所以我希望能够以非常有效的格式获得调试消息.
通常,调试语句类似于以下内容:
myDebugLibraryPrintf("Inside loop, processing item %d out of %d.\n", i, numItems);
Run Code Online (Sandbox Code Playgroud)
当然,当它被扩展为文本时,打印的字符串类似于"内部循环,处理项目5中的10个\n",总共约42个字节左右.此语句打印出的90%以上的数据是静态的,字面的 - 在编译时已知.当然,在编译时只知道"5"和"10".
我想做的是只能回发那两个整数(8个字节而不是42个).一旦我收到了这些数据,我就会有一些"解码器响铃"让我"重新构建"收到的数据并在我的位置打印出完整的调试信息.
我会自动生成"解码器环"(作为构建过程的一部分),在编译时为每个myDebugLibraryPrintf()语句提供一个唯一的ID,并生成一个将这些唯一ID映射到原始格式字符串的表.然后,任何时候myDebugLibraryPrintf()被调用的目标时,它发送该唯一ID和任何的"%d","%f"等可变参数格式字符串看到的值,但格式字符串本身不会被传送.(我"%s"现在可能只是禁止使用项目...)回到我的位置,我们将有一个程序查找表中的唯一ID,找到相应的格式字符串,并使用它来重建原始调试消息.
我觉得以前可能有人有这个想法,我想社区中的某个人可能会看到类似的东西(或者甚至知道这样做的开源库).
约束:
为了澄清,我在这里处理C/C++,我对printf()的100%完全替换实现不感兴趣 - 像非文字格式字符串,%s(字符串)格式说明符或更高级的东西格式说明符,例如将宽度或精度放在varargs列表中,%*.*d不需要支持.
我希望字符串表作为构建过程的一部分自动生成,因此添加调试不会比添加传统的printf()更多的工作.如果需要超过最小努力量,我项目中的任何人都不会使用它.
在生成字符串表的构建过程中做额外的工作几乎是假定的.幸运的是,我控制了我对使用这个库感兴趣的所有源代码,并且我在构建过程中有很大的灵活性.
谢谢!
我只见过用一组预定义的字符串实现这个想法。代码看起来像debug_print(INSIDE_LOOP_MSG_ID, i, n). 当开发人员想要添加新消息时,他们必须将新文本放入特定的头文件中并为其指定新的 ID。
我认为从看起来很正常的打印语句中动态生成它的想法是一个有趣的挑战。我还没有遇到任何现有的实现。
一个想法可能是一个宏/模板,它在编译时将第一个字符串参数转换为哈希值。所以开发人员编写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);
}
Run Code Online (Sandbox Code Playgroud)
只要稍微聪明一点,你就可以支持多个论点。检查 dissembly 表明所有哈希值确实是在编译时计算的。输出符合预期,相同字符串没有冲突。(本页确认 3.14 的十六进制是正确的):
Sending 94b7555c 1
Sending 62fce13e 2
Sending 506e9a0c 4048f5c3
Run Code Online (Sandbox Code Playgroud)
您现在需要的只是一个文本处理脚本,该脚本可以在从 Debug_Print 中提取字符串的代码上运行,计算哈希值并填充接收方的表。接收方从调用中获取哈希值Send,查找与之相关的字符串,并将其与参数一起传递给正常的 printf 调用。
我看到的唯一问题是编译时哈希中的嵌套宏使我的重构插件感到困惑并破坏了我的 IDE 响应能力。禁用加载项消除了该问题。