Linux运行时缺少的符号,如何在Linux中忽略运行时的未定义符号?

我知道默认情况下,在编译时会忽略未定义的符号.但是,我也希望它们在运行时被忽略.我需要分发一个使用和不使用MPI运行的.so.我会提前知道它是否是MPI工作,如果不是,我将不会进行任何MPI_ *调用.如果它不是MPI运行,我需要应用程序不关心它无法解析MPI_ *符号.

这可能吗?我本来可以发誓我之前做过这件事,但是我无法让它发挥作用.我每次运行时都会立即得到以下内容,即使我的代码中的逻辑永远不会允许引用该符号:

undefined symbol: hpmp_comm_world

为了我的价值,我使用英特尔Fortran编译器来构建.so文件.

编辑

我找到了链接器标志:“-z lazy”,它应该在调用函数时解析函数的引用,这就是我想要的.这不能解决我的问题,但是hpmp_comm_world是一个变量 – 而不是一个函数.这应该有所作为吗?

解决方法:

您可以将符号定义为对其定义的弱引用.然后,如果定义不存在,则符号的值将为零.

例如,假设以下是ref.c,它引用可能存在或不存在的函数和变量;我们将用它来构建libref.so(对应于你的库,在你的问题中):

#include

void global_func(void);

void global_func(void) __attribute__ ((weak));

extern int global_variable __attribute__((weak));

void ref_func() {

printf("global_func = %p\n", global_func);

if (&global_variable)

global_variable++;

if (global_func)

global_func();

}

这里,global_func和global_variable是对可能可用的函数和变量的弱引用.此代码打印函数的地址,如果存在则递增变量,并调用函数(如果存在). (注意,函数和变量的地址在未定义时为零,因此必须与& global_variable进行比较.)

假设这是def.c,它定义了global_func和global_variable;我们将用它来构建libdef.so(对应于你的问题中的MPI):

#include

int global_variable;

void global_func(void) {

printf("Hi, from global_func! global_variable = %d\n", global_variable);

}

最后,假设我们有一个主程序main.c,它从libref.so调用ref_func:

#include

extern void ref_func(void);

int main(int argc, char **argv) {

printf("%s: ", argv[0]);

ref_func();

return 0;

}

这是构建libref.so和libdef.so的Makefile,然后构建两个可执行文件,这两个可执行文件都链接到libref.so,但只有一个链接libdef.so:

all: ref-absent ref-present

ref-absent: main.o libref.so

$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@

ref-present: main.o libref.so libdef.so

$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@

lib%.so: %.o

$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ -o $@

ref.o def.o: CFLAGS += -fpic

clean:

rm -f *.o *.so ref-absent ref-present

做构建:

$make

cc -c -o main.o main.c

cc -fpic -c -o ref.o ref.c

cc -shared ref.o -o libref.so

cc main.o libref.so -o ref-absent

cc -fpic -c -o def.o def.c

cc -shared def.o -o libdef.so

cc main.o libref.so libdef.so -o ref-present

$

请注意,ref_ubsent和ref-present都没有问题链接,即使在ref_ubsent中没有global_name的定义.

现在我们可以运行程序,并看到ref-absent跳过函数调用,而ref-present使用它. (我们必须设置LD_LIBRARY_PATH以允许动态链接器在当前目录中找到我们的共享库.)

$LD_LIBRARY_PATH=. ./ref-absent

./ref-absent: global_func = (nil)

$LD_LIBRARY_PATH=. ./ref-present

./ref-present: global_func = 0x15d4ac

Hi, from global_func! global_variable = 1

$

你的诀窍是将((弱))属性附加到你的库引用的每个MPI函数的每个声明.但是,正如ref.c所示,可以有多个声明,只要其中一个提到弱属性,就完成了.所以你可能不得不说这样的话(我真的不知道MPI):

#include

mpi_fake_type_t mpi_function_foo(mpi_arg_type_t) __attribute__((weak));

mpi_fake_type_t mpi_function_bar(mpi_other_arg_type_t) __attribute__((weak));

每个对MPI函数的引用都需要在该函数的((弱))声明的范围内;这就是编译器决定放入目标文件的符号引用类型的方式.您需要进行自动化测试,以验证您是否未意外生成任何非弱引用.

标签:linux,linker

来源: https://codeday.me/bug/20190827/1739792.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值