Linux ld-共享成功,但在运行时出现分段错误

Linux ld-共享成功,但在运行时出现分段错误,linux,gcc,ld,Linux,Gcc,Ld,我是一个初学者,学习基本的编译。我创建了一个非常简单的c文件,如下所示 #include <stdio.h> int main (void) { printf("Hello World!\n"); return 0; } 在这里,我收到了这样的错误信息 ld -shared -o helloworld /usr/lib64/libc.so helloworld.o ld: helloworld.o: relocation R_X86_64_32 aga

我是一个初学者,学习基本的编译。我创建了一个非常简单的c文件,如下所示

#include <stdio.h>

int main (void) {
  printf("Hello World!\n");
  return 0;
}
在这里,我收到了这样的错误信息

ld -shared -o helloworld /usr/lib64/libc.so helloworld.o
ld: helloworld.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Nonrepresentable section on output
所以我用a-fPIC重新运行了upper

cpp -E helloworld.c -o helloworld.i
gcc -S helloworld.i -o helloworld.s -fPIC
as helloworld.s -o helloworld.o
ld -shared -o helloworld /usr/lib64/libc.so helloworld.o
最后,我得到了我的helloworld,但是当我尝试时,我得到了一个分割错误


有人能帮忙吗?提前谢谢

我尝试了gcc helloworld.c-Wl,--verbose | grep成功了,并获得了如下输出:

attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o succeeded
attempt to open /tmp/ccSuIvy2.o succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc.a succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc_s.so succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/libc.so succeeded
attempt to open /lib64/libc.so.6 succeeded
attempt to open /usr/lib64/libc_nonshared.a succeeded
attempt to open /lib64/ld-linux-x86-64.so.2 succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc.a succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc_s.so succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o succeeded
attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o succeeded
但我仍然不知道如何做链接,我尝试了这个

ld -shared -o helloworld /usr/lib64/libc.so /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc_s.so /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib64/crtn.o helloworld.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/libgcc.a /usr/lib64/libc_nonshared.a /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o 
但是得到一个错误消息

ld: /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: relocation R_X86_64_32S against undefined symbol `__libc_csu_fini' can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Nonrepresentable section on output

您是否有理由尝试单独执行构建的每个部分,而不是使用
gcc
在一个命令中构建所有部分?那就是gcc-o helloworld helloworld.c?您的命令不够,因为需要链接的不仅仅是
libc
。运行
gcc-v helloworld.c
查看gcc执行的确切步骤,并与您现有的步骤进行比较。是的,gcc-o helloworld helloworld.c可以工作,但我试图了解ld命令的工作原理,这就是为什么我这样做的原因。gcc-v输出对我来说有点复杂。请你再详细说明一下好吗?非常感谢!然后,查看
gcc-v
输出以更好地理解命令细节。这并不像你现在做的那么简单。好的,任何解释gcc-v输出的web链接都是非常感谢的!我发现,您必须使用
-fPIC
(或
-fPIC
)为共享库生成位置无关的代码,因为必须通过全局偏移量而不是相对于加载库的程序的地址来访问共享库——否则,每次加载库时,相对偏移量将引用不同的位置。请参见
-fpic
选项下的
mangcc
。但是crtl.o不是我创建的,它是由ubuntu提供的,对吗?没错,如果您想要任何东西,包括加载helloworld的c运行时,那么它必须具有全局偏移量。更大的问题是你试图完成什么。您没有将代码用作共享库。为什么不使用打印helloworld的函数创建一个单独的源代码,并将其编译为共享库,然后将其与main()链接并调用打印helloworld的函数?
ld: /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: relocation R_X86_64_32S against undefined symbol `__libc_csu_fini' can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Nonrepresentable section on output