segfault消息的行为取决于执行环境



我试图理解为什么segfault消息的行为会因执行环境而异。

我有以下C代码,我正在使用它来故意触发segfault:

#include <stdio.h>
int main() {
int* p = NULL;
printf("%dn", *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,消息不会出现(。但是在我的本地Linux上,segfault消息并没有写入stderr。

我验证了在本地Linux系统中交互式运行Docker容器时,将stdout和stderr重定向到/dev/null也会导致容器的交互式shell输出中出现segfault消息:

$ gcc segfault.c 
$ ./a.out >/dev/null 2>&1
Segmentation fault (core dumped)

我查看了sh步骤的Java源代码,但对我来说,没有什么能成为Jenkins中这种不同行为的原因(但很可能我错过了什么(。

我的本地Linux是Ubuntu 20.04。我在Jenkins上使用的Docker镜像是gcc镜像。两者都使用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。

为什么詹金斯的行为与当地不同?

原因是以下原因之一吗?还是别的什么?

  • Docker容器和非Docker Linux之间的区别
  • 我编译的gcc版本的差异
  • 一些神奇的詹金斯的东西

它是调用./segfault的shell。如果您在计算机上切换到dash并运行相同的命令,您也不会在那里看到Segmentation fault消息。

  1. 定义任何变量/对象时,始终初始化它
  2. 使用任何指针时,只有在不为NULL时才使用它们
  3. 下面是调用用户定义函数"的示例程序;mysig";当接收到SIGSEGV信号时。当我们使用NULL指针时,程序接收信号SIGSEGV(分段错误(。我已经更新了代码;mysig";当分段故障发生时。一旦发生这种情况,它就将创建核心转储文件作为默认功能。一旦接收到该信号
  4. 在执行程序之前:
$ ulimit -c unlimited
$ ./a.out

以上程序将创建一个核心文件。使用核心文件,我们可以根据您的操作系统使用gdb.exe/gdb/dbx分析程序崩溃的位置。gdb在线教程:

https://www.tutorialspoint.com/gnu_debugger/index.htm

示例程序:

#include <sys/signal.h>
#include <stdio.h>
void mysig( int sig)
{
switch( sig )
{
case SIGSEGV:
printf("Never use NULL pointern");
signal( SIGSEGV, SIG_DFL);
break;
default:
printf( "Other signal: %dn", sig);
}
}
int main()
{
int* p = NULL;
signal( SIGSEGV, mysig);
if ( NULL == p )
{
printf("Never use NULL pointern");
}
else
{
printf("%dn", *p);
}
printf( "Make call to mysig by using NULL pointern");
printf("%dn", *p);
return 0;
}

样本输出:

$ gcc  -g -Wall 73596388.cpp -o ./a.out
$ ./a.out
Never use NULL pointer
Make call to mysig by using NULL pointer
Never use NULL pointer
Segmentation fault (core dumped)
$ # I compiled using bash.exe/gcc.exe at windows:
$ gdb a.out
Reading symbols from a.out...
(gdb) break main
Breakpoint 1 at 0x1004010d8: file 73596388.cpp, line 17.
(gdb) run
Starting program: ./a.out
[New Thread 10964.0x219c]
[New Thread 10964.0x2090]
[New Thread 10964.0x1dd4]
Thread 1 "a.out" hit Breakpoint 1, main () at 73596388.cpp:17
17              int* p = NULL;
(gdb) next
18              signal( SIGSEGV, mysig);
(gdb) next
19              if ( NULL == p )
(gdb) next
21                      printf("Never use NULL pointern");
(gdb) next
Never use NULL pointer
27              printf( "Make call to mysig by using NULL pointern");
(gdb) next
Make call to mysig by using NULL pointer
28              printf("%dn", *p);
(gdb) step
Thread 1 "a.out" received signal SIGSEGV, Segmentation fault.
0x0000000100401136 in main () at 73596388.cpp:28
28              printf("%dn", *p);
(gdb) step
Never use NULL pointer
Thread 1 "a.out" received signal SIGSEGV, Segmentation fault.
0x0000000100401136 in main () at 73596388.cpp:28
28              printf("%dn", *p);
(gdb) step
0 [main] a.out 33539 cygwin_exception::open_stackdumpfile: Dumping stack trace to a.out.stackdump
                                 [Thread 10964.0x2adc exited with code 35584]
[Thread 10964.0x2090 exited with code 35584]
[Thread 10964.0x219c exited with code 35584]
[Inferior 1 (process 10964) exited with code 0105400]
(gdb)

相关内容

  • 没有找到相关文章

最新更新