gpt4 book ai didi

c - 重定向断言失败消息

转载 作者:行者123 更新时间:2023-12-02 20:22:46 24 4
gpt4 key购买 nike

我们有一个具有实时约束的软件项目,主要用 C++ 编写,但使用了许多 C 库,在 POSIX 操作系统中运行。为了满足实时限制,我们已将几乎所有的文本移出 stderr管道并进入共享内存环形缓冲区。

我们现在遇到的问题是,当旧代码或 C 库调用 assert 时,消息最终位于 stderr而不是与其余日志一起存在于我们的环形缓冲区中。我们想找到一种方法来重定向 assert 的输出.

我考虑了三种基本方法:

1.) 创建我们自己的断言宏——基本上,不要使用 #include <cassert> ,给出我们自己的 assert 的定义。这可行,但是修补我们正在使用该调用 assert 的所有库将非常困难。包含不同的 header 。

2.) 修补 libc -- 修改 __assert_fail 的 libc 实现。这可行,但在实践中会非常尴尬,因为这意味着如果不构建日志基础设施,我们就无法构建 libc。我们可以这样做,以便在运行时,我们可以将函数指针传递给 libc这就是“断言处理程序”——这是我们可以考虑的。问题是是否有比这更简单/更少侵入性的解决方案。

3.) 修补 libc header ,以便 __assert_fail标有__attribute__((weak)) 。这意味着我们可以在链接时使用自定义实现覆盖它,但如果我们的自定义实现未链接,那么我们将链接到常规 libc 实现。实际上我希望这个函数已经被标记为 __attribute__((weak))我惊讶地发现事实并非如此。

我的主要问题是:选项(3)可能有哪些缺点——修补 libc 以使这一行:https://github.com/lattera/glibc/blob/master/assert/assert.h#L67

extern void __assert_fail (const char *__assertion, const char *__file,
unsigned int __line, const char *__function)
__THROW __attribute__ ((__noreturn__));

标有 __attribute__((weak))还有?

  1. 我有没有充分的理由没有想到维护者还没有这样做?
  2. 在我以这种方式修补 header 后,当前正在链接并成功运行 libc 的任何现有程序如何会中断?这不可能发生,对吧?
  3. 出于某种原因,在此处使用弱链接符号是否会产生显着的运行时成本? libc对于我们来说已经是一个共享库,我认为动态链接的成本应该淹没任何有关系统在加载时必须执行的弱解析与强解析的案例分析?
  4. 这里有我没有想到的更简单/更优雅的方法吗?

glibc 中的一些函数,特别是 strtodmalloc ,都标有特殊的 gcc 属性 __attribute__((weak)) 。这是一个链接器指令——它告诉 gcc 这些符号应该被标记为“弱符号”,这意味着如果在链接时找到该符号的两个版本,则选择“强”版本而不是弱版本。

维基百科上描述了这样做的动机:

Use cases

Weak symbols can be used as a mechanism to provide default implementations of functions that can be replaced by more specialized (e.g. optimized) ones at link-time. The default implementation is then declared as weak, and, on certain targets, object files with strongly declared symbols are added to the linker command line.

If a library defines a symbol as weak, a program that links that library is free to provide a strong one for, say, customization purposes.

Another use case for weak symbols is the maintenance of binary backward compatibility.

但是,在 glibc 和 musl libc 中,在我看来 __assert_fail函数(assert.h 宏转发到的函数)未标记为弱符号。

https://github.com/lattera/glibc/blob/master/assert/assert.h

https://github.com/lattera/glibc/blob/master/assert/assert.c

https://github.com/cloudius-systems/musl/blob/master/include/assert.h

最佳答案

您不需要 glibc 中的符号 __assert_fail 上的 attribute((weak))。只需在程序中编写您自己的 __assert_fail 实现,链接器应该使用您的实现,例如 example :

#include <stdio.h>
#include <assert.h>

void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function)
{
fprintf(stderr, "My custom message\n");
abort();
}


int main()
{
assert(0);
printf("Hello World");

return 0;
}

这是因为当链接器解析符号时,__assert_fail 符号已由您的程序定义,因此链接器不应选择 libc 定义的符号。

如果您确实需要将 __assert_fail 定义为 libc 内的弱符号,为什么不直接 objcopy --weaken-symbol=__assert_fail/lib/libc.so/lib/libc_with_weak_assert_fail.so。我认为您不需要为此从源代码重建 libc。

关于c - 重定向断言失败消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50915274/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com