头文件的多重引用问题

1 问题及解决

在写代码的时候发现了一个问题:我们知道,在一个工程中可能存在多个实现文件include同一个头文件,然后在最后链接的时候导致重声明错误,因此,我们一般使用编译器指令#pragma once或者#ifndef来解决该问题,但是仍然存在一种场景,是如上两种方法解决不了的。

实现文件的include层次如下:

在这里插入图片描述

然后,在utils.cuh中,我直接定义了一个handlError函数【注意,是定义,不是声明】:

void handleError(cudaError_t err, const char *file, const int line){
     if (err != cudaSuccess){
         printf("file: %s, line: %d: There is a error happening!\n", file, line);
         printf("The error reason is: %s\n", cudaGetErrorString(err));
         exit(-1);
     }
 }

于是,在我进行编译的时候,就会出现:

/tmp/tmpxft_000075d6_00000000-21_storage.o: In function `handleError(cudaError, char const*, int)':
tmpxft_000075d6_00000000-9_storage.cudafe1.cpp:(.text+0x267): multiple definition of `handleError(cudaError, char const*, int)'
/tmp/tmpxft_000075d6_00000000-18_blas_test.o:tmpxft_000075d6_00000000-5_blas_test.cudafe1.cpp:(.text+0x267): first defined here
/tmp/tmpxft_000075d6_00000000-24_blas.o: In function `handleError(cudaError, char const*, int)':
tmpxft_000075d6_00000000-13_blas.cudafe1.cpp:(.text+0x267): multiple definition of `handleError(cudaError, char const*, int)'
/tmp/tmpxft_000075d6_00000000-18_blas_test.o:tmpxft_000075d6_00000000-5_blas_test.cudafe1.cpp:(.text+0x267): first defined here
collect2: error: ld returned 1 exit status

可知该错误就是多重定义错误。这是怎么回事呢?看一下include层次图,在blas.cuh中出现了分支,但是分支都回到了utils.cuh上,于是,我们的handleError函数就被定义了两次,这肯定是不允许的。那这个问题怎么解决呢?有如下解决方法:

  • 第一种,我们一般情况下都不会在头文件中对函数进行定义,不然就可能会导致这个问题产生【这里是我写代码时犯的一个错误】。于是,我们选择头文件声明,对应的实现文件定义来解决这个问题。

  • 第二种,在该函数前面加inline声明:

    inline void handleError(cudaError_t err, const char *file, const int line){
         if (err != cudaSuccess){
             printf("file: %s, line: %d: There is a error happening!\n", file, line);
             printf("The error reason is: %s\n", cudaGetErrorString(err));
             exit(-1);
         }
     }
    

    为什么加inline有用呢?因为在头文件中放入了一个inline函数的定义,就保证了每个inline函数都只有一个定义。所以便可解决多重定义问题。并且,我们一般都在头文件中对inline函数进行声明,然后需要使用该inline函数的话,就include该头文件即可。最后补充一点,inline必须加在函数定义体前面才有效,加在函数声明前面是无效的。

2 总结

所以,为了避免多重定义问题,我们应该规范好自己的代码写作,保证:

  • 尽量让头文件声明,对应的实现文件进行定义;
  • 将inline函数的定义放在头文件中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值