2

有没有办法让 C/C++ 预处理器或模板等对 __FILE__ 和 __LINE__ 以及其他一些外部输入(如内部版本号)进行处理/散列到可以在日志或错误消息中引用的单个短数字中?

(目的是当客户在错误报告中引用它时,能够在需要时将其反转(如果它有损,则为候选列表)。)

4

6 回答 6

2

您将不得不使用一个函数来执行散列并从中创建代码__LINE____FILE__因为 C 预处理器无法执行如此复杂的任务。

无论如何,您可以从这篇文章中获得灵感,看看是否有不同的解决方案更适合您的情况。

于 2008-09-26T22:22:26.773 回答
0

好吧,如果您自己向用户显示消息(而不是让系统显示崩溃地址或功能),那么没有什么可以阻止您准确显示您想要的内容。

例如:

typedef union ErrorCode {
    struct {
        unsigned int file: 15;
        unsigned int line: 12; /* Better than 5 bits, still not great
                                  Thanks commenters!! */
        unsigned int build: 5;
    } bits;
    unsigned int code;
} ErrorCode;

unsigned int buildErrorCodes(const char *file, int line, int build)
{
    ErrorCode code;
    code.bits.line=line   & ((1<<12) - 1);
    code.bits.build=build & ((1<< 5) - 1);
    code.bits.file=some_hash_function(file) & ((1<<15) - 1);

    return code.code;
}

你会用它作为

buildErrorCodes(__FILE__, __LINE__, BUILD_CODE) 

并以十六进制输出。解码不会太难...

(已编辑 - 评论者是正确的,我一定是疯了,为行号指定 5 位。模 4096,但是,带有错误消息的行不太可能发生冲突。构建的 5 位仍然很好 - 模 32 意味着只有 32 个构建可以突出并且错误仍然发生在同一行。)

于 2008-09-26T22:20:10.943 回答
0

嗯......你可以使用类似的东西:

((*(int*)__FILE__ && 0xFFFF0000) | version << 8 | __LINE__ )

它不会是完全独特的,但它可能适用于您想要的。可以将这些 OR 更改为 +,这可能对某些事情更有效。

自然,如果您实际上可以创建哈希码,您可能会想要这样做。

于 2008-09-26T22:25:03.757 回答
0

我在我的一个项目中需要序列值,并通过制作一个专门用于__LINE____FILE__导致 int 的模板以及为它的输入生成(作为编译时输出到标准输出)模板专业化来获得它们,从而导致行号那个模板。这些是第一次通过编译器收集,然后转储到代码文件中,然后再次编译程序。那时,使用模板的每个位置都有不同的编号。

(在 D 中完成,因此在 C++ 中可能无法实现)

template Serial(char[] file, int line)
{
    prgams(msg, 
    "template Serial(char[] file : \"~file~"\", int line : "~line.stringof~")"
      "{const int Serial = __LINE__;");
    const int Serial = -1;
}
于 2008-09-26T22:33:00.383 回答
0

一个更简单的解决方案是保留一个全局静态“错误位置”变量。

#ifdef DEBUG
#define trace_here(version) printf("[%d]%s:%d {%d}\n", version, __FILE__, __LINE__, errloc++);
#else
#define trace_here(version) printf("{%lu}\n", version<<16|errloc++);
#endif

或者没有 printf.. 每次越过跟踪点时只需增加 errloc。然后,您可以很容易地将值与调试版本吐出的行/编号/版本相关联。

您需要包含版本或内部版本号,因为这些错误位置可能会随着任何版本的变化而改变。

如果您无法重现代码路径,则效果不佳。

于 2008-09-26T22:35:41.937 回答
0

__FILE__ 是指向程序常量段的指针。如果你输出它和其他一些常数之间的差异,你应该得到一个独立于任何重定位等的结果:

extern const char g_DebugAnchor;
#define FILE_STR_OFFSET (__FILE__ - &g_DebugAnchor)

然后你可以报告它,或者以某种方式将它与行号等结合起来。FILE_STR_OFFSET 的中间位可能是最有趣的。

于 2008-10-03T21:04:55.187 回答