【问题标题】:Solve redefinition of struct defined in two different OS-es解决在两个不同操作系统中定义的结构的重新定义
【发布时间】:2020-06-05 15:15:32
【问题描述】:

我在 QNX 下有一个项目。我正在尝试对其进行单元测试(gtest),但遇到以下问题:

在我的一个源文件中,我使用 sys/siginfo.h (https://www.qnx.com/developers/docs/6.4.1/neutrino/lib_ref/s/sigevent.html) 中的 sigevent 结构。

在我的单元测试中,我为 sys/siginfo.h 文件创建了一个存根文件,我在其中存根了 sigevent 结构,但它抱怨 redefinition 因为还有一个 sigevent 结构在linux下中 https://sites.uclouvain.be/SystInfo/usr/include/bits/siginfo.h.html.

这两个存根有不同的结构——我不能用一个代替另一个。 我不能使用命名空间,因为 sigevent 结构在我的源文件中使用,而不是在单元测试的存根文件中使用 - 我不允许更改源文件。

如果我能够更改源文件,那么使用命名空间也无法解决此问题,因为 sys/siginfo.h 不是用户定义的标头。我认为一个解决方案是 QNX 的 sys/siginfo.h 的包装器。

但是如何通过单元测试解决这个问题?

错误:

/stubs/sys/siginfo.h:166:8: 错误: 'struct sigevent' 的重新定义 结构 sigevent {

/usr/include/x86_64-linux-gnu/bits/siginfo.h:320:16:错误:以前 'struct sigevent' 的定义 typedef struct sigevent

P.S.:我将此问题标记为“C 编程”,因为它不完全是单元测试。

谢谢, 卡门

【问题讨论】:

  • 那么为什么要存根sigevent 结构呢?如果结构在两个系统上的 sysinfo.h 中都可用?那为什么要存根呢?
  • 您在 Linux 上的测试环境中对 QNX 下项目中的文件(或文件组)进行单元测试,我是否理解正确?
  • 一种解决方案可能是在您的项目设置(IDE、makefile 等)中定义保护 Linux'struct sigevent 的定义组合(也许 __have_sigevent_t 就足够了)。
  • 是的,@Peter-ReinstateMonica。该项目在 QNX 下运行,我正在 Linux 的测试环境中进行单元测试。我不明白您提出的解决方案:'定义保护 Linux struct sigevent 的定义组合'。请描述一下!
  • @KamilCuk QNX 的 sysinfo.h 仅在我在 QNX 上运行项目时可用,因此在测试环境中不可用。因此我必须存根它。这会导致错误,因为 Linux 有自己的存根版本。

标签: c unit-testing


【解决方案1】:

这个答案只是试探性的,但评论太长了。

情况是:您有一个要测试的软件,该软件设计为在 QNX 下运行,在某些嵌入式设备上。它使用struct sigevent,其实际定义取决于系统。您已经编写了一个模仿 QNX 版本的模拟程序,用于测试目的并独立于系统。

现在您在 Linux 下的软件环境中编写模块测试。

我的第一个问题是,当您最终在 QNX 下编译程序时,如何防止 struct sigevent 的重复定义(我假设您没有在 Linux 下交叉编译)。防止这种情况应该类似于在 Linux 下防止它。 (如果您确实在进行交叉编译,则需要修复该交叉编译环境;它应该带有自己的系统库来满足 QNX 的需要,并且默认情况下不包含 Linux 头文件。)

Linux 带有自己的struct sigevent,现在与您的发生冲突。我假设结构定义间接包含在例如signal.h,我认为您需要的标题。 (您也许应该首先确定您是否真的需要攻击性标题;也许您的文件中有多余的包含。)

最简单的情况是结构定义在它自己的头文件中,然后它有自己的包含保护,例如https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/bits/types/sigevent_t.h.html.

您只需在源文件的顶部定义__sigevent_t_defined,这将在所有包含的头文件中传递可见并防止包含该头文件(因此重新定义struct sigevent):

#define __sigevent_t_defined
#include <signal.h> // or whatever
//...
struct sigevent { /* mock definition, no collision */ };

这里一个可能的问题是其他标头中的代码可能会访问您的模拟不包含的原始结构的成员。更糟糕的是,Linux 库代码可能会发现 struct sigevent 的意外布局(毕竟它是使用不同的结构定义编译的)。您不能将 Linux 库函数与 struct sigevent 一起使用,也不能间接使用(如果它包含在更大的结构中)。但是对于单元测试,您可能不必这样做。

我看到了另一个版本的sruct sigevent,它是更大标题的一部分,并受到#defines 的某种组合的“保护”,但我现在找不到它。你的编译器的错误信息应该告诉你冲突定义的位置;看看它,找出你必须定义什么才能使该结构定义“不可见”。

【讨论】:

  • bits/siginfo.h 直接或间接包含在我包含在主测试文件中的 gtest/gtest.h 中。在 qnx 下编译项目时,我不必在 linux 或 qnx 文件之间进行选择。
  • 我在包含 gtest/gtest.h 文件之前定义了 _SYS_WAIT_H 保护,问题就解决了。确实,将来我可能在单元测试中需要这个文件(wait.h),所以我需要找到一个更具体的文件来排除......谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
相关资源
最近更新 更多