我试图理解为什么segfault消息的行为会因执行环境的不同而不同。
我有下面的C代码,我使用它来故意触发segfault:
# include <stdio.h>
int main() {
int* p = NULL;
printf("%d\n", *p);
}
在我的本地Linux上,当我编译这段代码并执行生成的二进制文件时,即使我将stdout和stderr都重定向到/dev/null
,也会看到segfault消息:
$ ./segfault > /dev/null 2>&1
Segmentation fault (core dumped)
$
在Jenkins的Docker容器中,我编译并运行完全相同的C代码,使用sh
步骤运行二进制代码,如下所示:
sh './segfault > /dev/null || true'
sh './segfault > /dev/null 2>&1 || true'
以下是Jenkins中的输出:
+ ./segfault
Segmentation fault (core dumped)
+ true
+ ./segfault
+ true
正如您所看到的,segfault消息被写入Jenkins中的stderr(您可以从我没有重定向到stderr时,消息出现,但如果我重定向到stderr,消息就不会出现中看到这一点)。但segfault消息没有写入我本地Linux上的stderr。
我验证了在本地Linux系统中以交互方式运行Docker容器时,将stdout和stderr重定向到/dev/null
也会导致segfault消息出现在容器的交互式shell输出中:
$ gcc segfault.c
$ ./a.out >/dev/null 2>&1
Segmentation fault (core dumped)
我查看了sh
步骤的Java源代码,但在Jenkins中,没有什么值得注意的地方可以作为这种不同行为的原因(但很可能我遗漏了一些东西)。
我的本地Linux是Ubuntu 20.04,我在Jenkins上使用的Docker映像是gcc image,两者都使用x86_64架构。
在我的本地Linux上,下面是我的内核发布版本:
$ uname -rv
5.13.0-30-generic #33~20.04.1-Ubuntu SMP Mon Feb 7 14:25:10 UTC 2022
这与gcc映像的内核发行版和内核版本完全匹配(在编写本文时)。
我的本地Linux有gcc 9.4.0,并且(在撰写本文时)gcc映像有gcc 12.2.0。
为什么Jenkins的行为与当地不同?
是以下原因之一?还是其他原因?
- Docker容器和非Docker Linux之间的区别
- gcc版本I编译时使用的差异
- 一些神奇的Jenkins的东西
2条答案
按热度按时间atmip9wb1#
它是调用
./segfault
的shell。如果你在你的计算机上切换到dash
并运行同样的命令,你也不会在那里看到 Segmentation fault 消息。daolsyd02#
1.定义任何变量/对象时,始终对其进行初始化。
1.使用任何指针时,仅在非NULL时使用它们
1.以下示例程序在接收SIGSEGV信号时调用用户定义的函数“mysig”。当我们使用NULL指针时,程序接收信号SIGSEGV(分段错误)。我更新了代码,以便在发生分段错误时调用“mysig”。一旦发生分段错误,它将使用默认函数创建核心转储文件。一旦接收到该信号,它将
1.在执行程序之前:
上面的程序将创建一个核心文件。使用核心文件,我们可以分析程序崩溃的地方使用gdb.exe/gdb/dbx基于您的操作系统。gdb教程在线:
示例程序:
示例输出: