gpt4 book ai didi

c - 由于C文件中的一行代码而发生段错误,并且整个程序无法运行

转载 作者:行者123 更新时间:2023-12-04 10:48:40 24 4
gpt4 key购买 nike

我已经创建了一个C程序来写入嵌入式ARM系统上的串行端口(/ dev / ttyS0)。在嵌入式ARM系统上运行的内核是Linux版本3.0.4,该内核使用与以下所列相同的交叉编译器构建。

我的交叉编译器是arm-linux-gcc(Buildroot 2011.08)4.3.6,它在Ubuntu x86_64主机(3.0.0-14-通用#23-Ubuntu SMP)上运行。我已使用stty实用程序从命令行设置串行端口。

奇怪的是,如果只有一行代码,该程序似乎将拒绝在嵌入式ARM系统上运行。如果删除该行,程序将运行。

这是复制该问题的完整代码:

编辑:我现在关闭错误的文件,如下面的注释中所建议。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <termios.h>

int test();
void run_experiment();

int main()
{
run_experiment();
return 0;
}

void run_experiment()
{
printf("Starting program\n");
test();
}

int test()
{
int fd;
int ret;

fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
printf("fd = %u\n", fd);
if (fd < 0)
{
close(fd);
return 0;
}

fcntl(fd, F_SETFL, 0);

printf("Now writing to serial port\n");

//TODO:
// segfault occurs due to line of code here
// removing this line causes the program to run properly
ret = write( fd, "test\r\n", sizeof("test\r\n") );

if (ret < 0)
{
close(fd);
return 0;
}
close(fd);
return 1;
}


该程序在ARM系统上的输出如下:

Segmentation fault


但是,如果删除上面列出的行并重新编译程序,问题就消失了,输出如下:

Starting program
fd = 3
Now writing to serial port


这里可能出什么问题,如何调试该问题?这是代码,交叉编译器或OS版本的问题吗?

打开文件时,我还尝试了不带O_NOCTTY的O_WRONLY和O_RDWR的各种组合,但是问题仍然存在。

正如@wildplasser在下面的注释中所建议的那样,我已在很大程度上基于另一个站点(http://www.warpspeed.com.au/cgi-bin/inf2html.cmd? .. \ html \ book \ Toolkt40 \ XPG4REF.INF + 112)。

但是,该程序仍然无法运行,并且我再次收到神秘的 Segmentation Fault

这是代码:

int test()
{
int fh;
FILE *fp;
char *cp;

if (-1 == (fh = open("/dev/ttyS0", O_RDWR)))
{
perror("Unable to open");
return EXIT_FAILURE;
}
if (NULL == (fp = fdopen(fh, "w")))
{
perror("fdopen failed");
close(fh);
return EXIT_FAILURE;
}

for (cp = "hello world\r\n"; *cp; cp++)
fputc( *cp, fp);

fclose(fp);
return 0;
}


这非常神秘,因为使用我编写的其他程序,我可以类似的方式使用 write()函数写入sysfs文件,而没有任何问题。

但是,如果程序的结构完全相同,则无法写入/ dev / null。

但是我可以使用完全相同的程序成功写入sysfs文件!

如果segfault发生在函数中的特定行上,则我认为该函数调用将导致segfault。但是,完整程序无法运行!

更新:为了提供更多信息,这是用于在ARM系统上构建的交叉编译器信息:

$ arm-linux-gcc --v
使用内置规格。
目标:arm-unknown-linux-uclibcgnueabi
配置为:/media/RESEARCH/SAS2-version2/device-system/buildroot/buildroot-2011.08/output/toolchain/gcc-4.3.6/configure --prefix = / media / RESEARCH / SAS2-version2 / device-system / buildroot / buildroot-2011.08 / output / host / usr --build = x86_64-unknown-linux-gnu --host = x86_64-unknown-linux-gnu --target = arm-unknown-linux-uclibcgnueabi --enable-languages = c,c ++ --with-sysroot = / media / RESEARCH / SAS2-version2 / device-system / buildroot / buildroot-2011.08 / output / host / usr / arm-unknown-linux-uclibcgnueabi / sysroot --with-build-time -tools = / media / RESEARCH / SAS2-version2 / device-system / buildroot / buildroot-2011.08 / output / host / usr / arm-unknown-linux-uclibcgnueabi / bin --disable -__ cxa_atexit --enable-target-optspace- -disable-libgomp --with-gnu-ld --disable-libssp --disable-multilib --enable-tls --enable-shared --with-gmp = / media / RESEARCH / SAS2-version2 / device-system / buildroot / buildroot-2011.08 / output / host / usr --with-mpfr = / media / RESEARCH / SAS2-version2 / device-system / buildroot / buildroot-2011.08 / output / host / usr --disable-n ls --enable-threads --disable-decimal-float --with-float = soft --with-abi = aapcs-linux --with-arch = armv5te --with-tune = arm926ej-s --disable-largefile --with-pkgversion ='Buildroot 2011.08'--with-bugurl = http://bugs.buildroot.net/
螺纹型号:posix
gcc版本4.3.6(Buildroot 2011.08)

这是我用来编译代码的makefile:

CC=arm-linux-gcc
CFLAGS=-Wall
datacollector: datacollector.o

clean:
rm -f datacollector datacollector.o


更新:使用下面的注释和答案中给出的调试建议,我发现该段错误是由在字符串中包含 \r转义序列引起的。由于某些奇怪的原因,编译器不喜欢 \r转义序列,并且会在不运行代码的情况下导致段错误。

如果删除了 \r转义序列,则代码将按预期运行。

因此,令人反感的代码行应为以下内容:

ret = write(fd,“ test \ n”,sizeof(“ test \ n”));

因此,为了记录在案,以下是一个实际运行的完整测试程序(有人可以评论吗?):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <termios.h>

int test();
void run_experiment();

int main()
{
run_experiment();

return 0;
}

void run_experiment()
{
printf("Starting program\n");
fflush(stdout);
test();
}


int test()
{
int fd;
int ret;
char *msg = "test\n";
// NOTE: This does not work and will cause a segfault!
// even if the fflush is called after each printf,
// the program will still refuse to run
//char *msg = "test\r\n";

fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
printf("fd = %u\n", fd);
fflush(stdout);

if (fd < 0)
{
close(fd);
return 0;
}

fcntl(fd, F_SETFL, 0);

printf("Now writing to serial port\n");
fflush(stdout);

ret = write( fd, msg, strlen(msg) );

if (ret < 0)
{
close(fd);
return 0;
}

close(fd);

return 1;
}


编辑:除了所有这些,最好使用:

ret = write( fd, msg, sizeof(msg) );


还是更好地使用:

ret = write( fd, msg, strlen(msg) );


哪个更好?使用sizeof()还是strlen()更好?似乎字符串中的某些数据已被截断,并且未使用sizeof()函数写入串行端口。

从下面Pavel的评论可以理解,如果将 strlen()声明为 msg,则最好使用 char*

此外,当使用转义序列 \r写入tty时,gcc似乎没有创建适当的二进制文件。

参考上面我的帖子中给出的最后一个测试程序,以下代码行导致了segfault,而程序未运行:

char *msg = "test\r\n";


正如伊戈尔(Igor)在评论中所建议的那样,我已经使用有问题的代码在二进制文件上运行了gdb调试器。我必须用 -g开关编译程序。
gdb调试器在ARM系统上本地运行,并且所有二进制文件均使用相同的Makefile在主机上针对ARM体系结构构建。所有二进制文件都是使用arm-linux-gcc交叉编译器构建的。

gdb的输出(在ARM系统上本地运行)如下:

GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-unknown-linux-uclibcgnueabi"...
"/programs/datacollector": not in executable format: File format not recognized
(gdb) run
Starting program:
No executable file specified.
Use the "file" or "exec-file" command.
(gdb) file datacollector
"/programs/datacollector": not in executable format: File format not recognized
(gdb)


但是,如果将单行代码更改为以下代码,则二进制文件会编译并正常运行。请注意,缺少 \r转义序列:

char *msg = "test\n";


这是更改单行代码后gdb的输出:

GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-unknown-linux-uclibcgnueabi"...
(gdb) run
Starting program: /programs/datacollector
Starting program
fd = 4
Now writing to serial port
test
Program exited normally.
(gdb)


更新:

正如Zack在下面的答案中所建议的那样,我现在已经在嵌入式系统上运行了一个测试程序
Linux系统。尽管Zack提供了详细的脚本以在嵌入式系统上运行,但我当时还是
由于缺少根文件系统中安装的开发工具(编译器和头文件),因此无法运行脚本。
代替安装这些工具,我只是编译了Zack在脚本中提供的漂亮测试程序,并
使用了strace实用程序。 strace实用程序在嵌入式系统上运行。

最后,我认为我了解发生了什么。

使用SPI到以太网桥(KSZ8851SNL),不良二进制文件通过FTP传输到嵌入式系统。
Linux内核中有KSZ8851SNL的驱动程序。

似乎是Linux内核驱动程序,嵌入式系统上运行的proftpd服务器软件或实际硬件本身(KSZ8851SNL)
在某种程度上破坏了二进制文件。二进制文件在嵌入式系统上运行良好。

这是通过以太网串行链路传输到嵌入式Linux系统的testz二进制文件上strace的输出:

错误的二进制测试:

# strace ./testz /dev/null
execve("./testz", ["./testz", "/dev/null"], [/* 17 vars */]) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x40089000
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Segmentation fault

# strace ./testz /dev/ttyS0
execve("./testz", ["./testz", "/dev/ttyS0"], [/* 17 vars */]) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x400ca000
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Segmentation fault
#


这是在SD卡上传输到嵌入式Linux系统的testz二进制文件上strace的输出:

好的二进制测试:

#  strace ./testz /dev/null
execve("./testz", ["./testz", "/dev/null"], [/* 17 vars */]) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x40058000
open("/lib/libc.so.0", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=298016, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x400b8000
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\240\230\0\0004\0\0\0"..., 4096) = 4096
mmap2(NULL, 348160, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40147000
mmap2(0x40147000, 290576, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x40147000
mmap2(0x40196000, 4832, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x47) = 0x40196000
mmap2(0x40198000, 14160, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40198000
close(3) = 0
munmap(0x400b8000, 4096) = 0
stat("/lib/ld-uClibc.so.0", {st_mode=S_IFREG|0755, st_size=25296, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x400c4000
set_tls(0x400c4470, 0x400c4470, 0x4007b088, 0x400c4b18, 0x40) = 0
mprotect(0x40196000, 4096, PROT_READ) = 0
mprotect(0x4007a000, 4096, PROT_READ) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0
open("/dev/null", O_RDWR|O_NOCTTY|O_NONBLOCK) = 3
write(3, "1\n", 2) = 2
write(3, "12\n", 3) = 3
write(3, "123\n", 4) = 4
write(3, "1234\n", 5) = 5
write(3, "12345\n", 6) = 6
write(3, "1\r\n", 3) = 3
write(3, "12\r\n", 4) = 4
write(3, "123\r\n", 5) = 5
write(3, "1234\r\n", 6) = 6
close(3) = 0
exit_group(0) = ?


# strace ./testz /dev/ttyS0
execve("./testz", ["./testz", "/dev/ttyS0"], [/* 17 vars */]) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x400ed000
open("/lib/libc.so.0", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=298016, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x40176000
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\240\230\0\0004\0\0\0"..., 4096) = 4096
mmap2(NULL, 348160, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40238000
mmap2(0x40238000, 290576, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x40238000
mmap2(0x40287000, 4832, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x47) = 0x40287000
mmap2(0x40289000, 14160, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40289000
close(3) = 0
munmap(0x40176000, 4096) = 0
stat("/lib/ld-uClibc.so.0", {st_mode=S_IFREG|0755, st_size=25296, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x400d1000
set_tls(0x400d1470, 0x400d1470, 0x40084088, 0x400d1b18, 0x40) = 0
mprotect(0x40287000, 4096, PROT_READ) = 0
mprotect(0x40083000, 4096, PROT_READ) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B115200 opost isig icanon echo ...}) = 0
open("/dev/ttyS0", O_RDWR|O_NOCTTY|O_NONBLOCK) = 3
write(3, "1\n", 21
) = 2
write(3, "12\n", 312
) = 3
write(3, "123\n", 4123
) = 4
write(3, "1234\n", 51234
) = 5
write(3, "12345\n", 612345
) = 6
write(3, "1\r\n", 31
) = 3
write(3, "12\r\n", 412
) = 4
write(3, "123\r\n", 5123
) = 5
write(3, "1234\r\n", 61234
) = 6
close(3) = 0
exit_group(0) = ?

最佳答案

编辑:请继续阅读以获取详细信息,但是快速的答案是,您的FTP客户端损坏了您的程序。这是FTP的一项有意功能,可以通过在binaryget whatever之前的FTP提示符下键入put whatever来关闭它。如果您使用的是图形FTP客户端,则应该在某处具有相同效果的复选框。或切换到不具有此不便功能的scp



首先,生成的汇编代码没有区别
(其中一个)工作目标文件和损坏的目标文件之间。

$ objdump -dr dc-good.o > dc-good.s
$ objdump -dr dc-bad.o > dc-bad.s
$ diff -u dc-good.s dc-bad.s
--- dc-good.s 2012-01-21 08:20:05.318518596 -0800
+++ dc-bad.s 2012-01-21 08:20:10.954566852 -0800
@@ -1,5 +1,5 @@

-dc-good.o: file format elf32-littlearm
+dc-bad.o: file format elf32-littlearm


Disassembly of section .text:


实际上,商品和商品之间只有两个字节不同
错误的目标文件。 (您误解了我的要求
"test\r\n""testX\n":我希望两个字符串成为
相同的长度,以便所有内容在
目标文件。幸运的是,您的编译器将较短的字符串填充为
与较长的字符串相同的长度,因此所有内容都相同
偏移。)

$ hd dc-good.o > dc-good.x
$ hd dc-bad.o > dc-bad.x
$ diff -u1 dc-good.x dc-bad.x
--- dc-good.x 2012-01-21 08:17:28.713174977 -0800
+++ dc-bad.x 2012-01-21 08:17:39.129264489 -0800
@@ -154,3 +154,3 @@
00000990 53 74 61 72 74 69 6e 67 20 70 72 6f 67 72 61 6d |Starting program|
-000009a0 00 00 00 00 74 65 73 74 58 0a 00 00 2f 64 65 76 |....testX.../dev|
+000009a0 00 00 00 00 74 65 73 74 58 0d 0a 00 2f 64 65 76 |....testX.../dev|
000009b0 2f 74 74 79 53 30 00 00 66 64 20 3d 20 25 75 0a |/ttyS0..fd = %u.|
@@ -223,3 +223,3 @@
00000de0 61 72 69 65 73 2f 64 61 74 61 63 6f 6c 6c 65 63 |aries/datacollec|
-00000df0 74 6f 72 2d 62 61 64 2d 62 69 6e 61 72 79 2d 32 |tor-bad-binary-2|
+00000df0 74 6f 72 2d 62 61 64 2d 62 69 6e 61 72 79 2d 31 |tor-bad-binary-1|
00000e00 00 46 49 4c 45 00 5f 5f 73 74 61 74 65 00 5f 5f |.FILE.__state.__|


第一个区别是应该存在的区别: 74 65 73
74 58 0a 00 00
"test\n"的正确编码(带有一个字节)
的填充), 74 65 73 74 58 0d 0a 00
"test\r\n"。另一个区别似乎是调试
信息:您在其中编译目录的名称
程式。这是无害的。

目标文件是应该的,因此在这一点上我们可以确定
找出编译器或汇编器中的错误。现在让我们看一下
可执行文件。

$ hd dc-good > dc-good.xe
$ hd dc-bad > dc-bad.xe
$ diff -u1 dc-good.xe dc-bad.xe
--- dc-good.xe 2012-01-21 08:31:33.456437417 -0800
+++ dc-bad.xe 2012-01-21 08:31:38.388480238 -0800
@@ -120,3 +120,3 @@
00000770 f0 af 1b e9 53 74 61 72 74 69 6e 67 20 70 72 6f |....Starting pro|
-00000780 67 72 61 6d 00 00 00 00 74 65 73 74 58 0a 00 00 |gram....testX...|
+00000780 67 72 61 6d 00 00 00 00 74 65 73 74 58 0d 0a 00 |gram....testX...|
00000790 2f 64 65 76 2f 74 74 79 53 30 00 00 66 64 20 3d |/dev/ttyS0..fd =|
@@ -373,3 +373,3 @@
00001750 63 6f 6c 6c 65 63 74 6f 72 2d 62 61 64 2d 62 69 |collector-bad-bi|
-00001760 6e 61 72 79 2d 32 00 46 49 4c 45 00 5f 5f 73 74 |nary-2.FILE.__st|
+00001760 6e 61 72 79 2d 31 00 46 49 4c 45 00 5f 5f 73 74 |nary-1.FILE.__st|
00001770 61 74 65 00 5f 5f 67 63 73 00 73 74 64 6f 75 74 |ate.__gcs.stdout|


相同的两个差异,可执行文件中的偏移量不同。这个
也是应该的。我们也可以排除链接器中的错误
(如果它搞砸了字符串的地址,那一定是
在两个可执行文件中以相同的方式将其固定起来,它们都应该
崩溃)。

在这一点上,我认为我们正在寻找您的C库中的错误或
核心。为了进一步说明问题,我希望您尝试此测试
脚本。在ARM板上以 sh testz.sh身份运行它,然后将其发送给我们
完成输出。

#! /bin/sh

set -e
cat >testz.c <<\EOF
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define W(f, s) write(f, s, sizeof s - 1)

int
main(int ac, char **av)
{
int f;
if (ac != 2) return 2;
f = open(av[1], O_RDWR|O_NOCTTY|O_NONBLOCK);
if (f == -1) return 1;

W(f, "1\n");
W(f, "12\n");
W(f, "123\n");
W(f, "1234\n");
W(f, "12345\n");

W(f, "1\r\n");
W(f, "12\r\n");
W(f, "123\r\n");
W(f, "1234\r\n");

close(f);
return 0;
}
EOF

arm-linux-gcc -Wall -g testz.c -o testz
set +e
strace ./testz /dev/null
echo ----
strace ./testz /dev/ttyS0
echo ----
exit 0




我已经查看了您提供的损坏的二进制文件,现在我知道出了什么问题。

$ ls -l testz*
-rwxr-x--- 1 zack zack 7528 Dec 31 1979 testz-bad
-rwxr-x--- 1 zack zack 7532 Jan 21 16:35 testz-good


忽略奇数戳;看看 -bad版本如何比 -good版本小四个字节?源代码中恰好有四个 \r字符。让我们看一下十六进制转储中的差异。我已经抽出了一些有趣的差异,并对其进行了一些改组,以便更轻松地了解发生了什么。

 00000620  00 00 00 00 31 32 33 34  0a 00 00 00 31 32 33 34  |....1234....1234|

-00000630 35 0a 00 00 31 0d 0a 00 31 32 0d 0a 00 00 00 00 |5...1...12......|
+00000630 35 0a 00 00 31 0a 00 31 32 0a 00 00 00 00 31 32 |5...1..12.....12|

-00000640 31 32 33 0d 0a 00 00 00 31 32 33 34 0d 0a 00 00 |123.....1234....|
+00000640 33 0a 00 00 00 31 32 33 34 0a 00 00 00 00 00 00 |3....1234.......|

-00000650 00 00 00 00 68 84 00 00 1c 84 00 00 00 00 00 00 |....h...........|
+00000650 68 84 00 00 1c 84 00 00 00 00 00 00 01 00 00 00 |h...............|


文件传输将 0d 0a(即 \r\n)序列替换为 0a(仅 \n)。这会导致文件中此点之后的所有内容从原先的位置偏移四个字节。代码在此之前,内核查看的所有ELF标头也是如此,这就是为什么您不明白的原因

execve("./testz-bad", ["./testz-bad", "/dev/null"], [/* 36 vars */]) = -1 ENOEXEC (Exec format error)


从测试脚本;相反,您会在动态加载程序内遇到段错误,因为DYNAMIC段(告诉动态加载程序要做什么)是在位移开始之后。

$ readelf -d testz-bad 2> /dev/null

Dynamic section at offset 0x660 contains 13 entries:
Tag Type Name/Value
0x00000035 (<unknown>: 35) 0xc
0x0000832c (<unknown>: 832c) 0xd
0x00008604 (<unknown>: 8604) 0x19
0x00010654 (<unknown>: 10654) 0x1b
0x00000004 (HASH) 0x1a
0x00010658 (<unknown>: 10658) 0x1c
0x00000004 (HASH) 0x4
0x00008108 (<unknown>: 8108) 0x5
0x0000825c (<unknown>: 825c) 0x6
0x0000815c (<unknown>: 815c) 0xa
0x00000098 (<unknown>: 98) 0xb
0x00000010 (SYMBOLIC) 0x15
0x00000000 (NULL) 0x3


对比:

$ readelf -d testz-good

Dynamic section at offset 0x660 contains 18 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x0000000c (INIT) 0x832c
0x0000000d (FINI) 0x8604
0x00000019 (INIT_ARRAY) 0x10654
0x0000001b (INIT_ARRAYSZ) 4 (bytes)
0x0000001a (FINI_ARRAY) 0x10658
0x0000001c (FINI_ARRAYSZ) 4 (bytes)
0x00000004 (HASH) 0x8108
0x00000005 (STRTAB) 0x825c
0x00000006 (SYMTAB) 0x815c
0x0000000a (STRSZ) 152 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x10718
0x00000002 (PLTRELSZ) 56 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x82f4
0x00000000 (NULL) 0x0


调试信息也在替换之后,这就是为什么gdb不喜欢该程序的原因。



那么,为什么这种非常特殊的腐败呢?这不是任何东西的错误;这是FTP客户端的一项有意功能,默认情况下以“文本模式”传输文件,这意味着(除其他事项外)它将DOS样式的行尾( \r\n)转换为Unix样式( \n)。因为如果这是1991年,并且您正在将文本文件从IBM PC传输到机构文件服务器,那将是您想要的。如今,即使您正在移动文本文件,也基本上不再需要它。幸运的是,您可以将其关闭:只需在文件传输命令之前的FTP提示符下键入 binary。 *不幸的是,据我所知,没有办法使它坚持下去。您必须每次都这样做。我建议切换到 scp,它总是逐字传输文件,并且在构建自动化中也更易于操作。

关于c - 由于C文件中的一行代码而发生段错误,并且整个程序无法运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8929599/

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