【问题标题】:How to avoid multiple definition linking error?如何避免多定义链接错误?
【发布时间】:2011-06-06 23:07:49
【问题描述】:

除了将 hello() 函数移动到另一个源 (.cpp) 文件或重命名函数之外。有没有其他方法可以避免链接错误?

staticLibA.h

#ifndef _STATIC_LIBA_HEADER
#define _STATIC_LIBA_HEADER

int hello(void);
int hello_staticLibA_only(void);

#endif

staticLibA.cpp

#include "staticLibA.h"

int hello(void)
{
    printf("\nI'm in staticLibA\n");
    return 0;
}

int hello_staticLibA_only(void)
{
    printf("\nstaticLibA: hello_staticLibA_only\n");
    return 0;
}

输出:

g++ -c -Wall -fPIC -m32 -o staticLibA.o staticLibA.cpp
ar -cvq ../libstaticLibA.a staticLibA.o
a - staticLibA.o

staticLibB.h

#ifndef _STATIC_LIBB_HEADER
#define _STATIC_LIBB_HEADER

int hello(void);
int hello_staticLibB_only(void);

#endif

staticLibB.cpp

#include "staticLibB.h"

int hello(void)
{
    printf("\nI'm in staticLibB\n");
    return 0;
}

int hello_staticLibB_only(void)
{
    printf("\nstaticLibB: hello_staticLibB_only\n");
    return 0;
}

输出:

g++ -c -Wall -fPIC -m32 -o staticLibB.o staticLibB.cpp 
ar -cvq ../libstaticLibB.a staticLibB.o 
a - staticLibB.o

ma​​in.cpp

extern int hello(void);
extern int hello_staticLibA_only(void);
extern int hello_staticLibB_only(void);

int main(void)
{
  hello();
  hello_staticLibA_only();
  hello_staticLibB_only();
  return 0;
}

输出:

g++ -c  -o main.o main.cpp
g++ -o multipleLibsTest main.o  -L. -lstaticLibA -lstaticLibB -lstaticLibC -ldl -lpthread -lrt
./libstaticLibB.a(staticLibB.o): In function `hello()':
staticLibB.cpp:(.text+0x0): multiple definition of `hello()'
./libstaticLibA.a(staticLibA.o):staticLibA.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [multipleLibsTest] Error 1

【问题讨论】:

    标签: c++ linux linker g++ multiple-definition-error


    【解决方案1】:

    由于您似乎拥有这两个库,因此不清楚为什么不能重命名该函数...

    在您的main 中,您有这行:

    hello();
    

    如果您让链接错误消失,您希望在这里发生什么?它应该调用LibA 还是LibB 中的实现?依靠将库传递给链接器的顺序来确定链接哪个函数似乎是一个非常糟糕的主意。在一个真实的例子中,如果你的hello_staticLibB_only 函数调用hello() 会发生什么?它最终可能会调用另一个库中的函数版本...

    当您使用g++ 时,您应该考虑将您的库函数放入namespace(它们旨在帮助您避免这种命名冲突)。这将允许您的代码和链接器分辨方法之间的区别。

    按照LibA 的这种方法,您将拥有:

    staticLibA.h

    #ifndef _STATIC_LIBA_HEADER
    #define _STATIC_LIBA_HEADER
    
    // Declare namespace to keep library functions together
    namespace LibA {
        int hello(void);
        int hello_staticLibA_only(void);
    }
    
    #endif
    

    staticLibA.cpp

    #include "staticLibA.h"
    #include <stdio.h>
    
    // Indicate that contained function definitions belong in the LibA namespace
    namespace LibA {
        int hello(void)
        {
            printf("\nI'm in staticLibA\n");
            return 0;
        }
    
        int hello_staticLibA_only(void)
        {
            printf("\nstaticLibA: hello_staticLibA_only\n");
            return 0;
        }
    }
    

    ma​​in.cpp

    // These declarations would usually be in a header... but I've left
    // them here to match your sample code...
    
    // declare relevant functions to belong to the LibA namespace
    namespace LibA{
        extern int hello(void);
        extern int hello_staticLibA_only(void);
    }
    
    // declare relevant functions from LibB (note they are not
    // in a namespace)
    extern int hello(void);
    extern int hello_staticLibB_only(void);
    
    int main(void)
    {
        // Explicitly call the hello from LibA
        LibA::hello();
        // Call the other library function (also from LibA)
        LibA::hello_staticLibA_only();
    
        // Call library functions from LibB (note they don't require a namespace
        // because I haven't updated it to have one)
        hello();
        hello_staticLibB_only();
        return 0;
    }
    

    【讨论】:

      【解决方案2】:

      链接错误特指hello。这是因为两个库都提供了“hello”的定义。这里没有其他链接错误。

      您可以将 hello 放在单独的库中,让 hello 驻留在单独的库中,或者只将可执行链接与 hello 对象文件 [hello.o] 进行关联

      【讨论】:

        猜你喜欢
        • 2019-08-14
        • 1970-01-01
        • 2011-07-31
        • 2016-03-12
        • 1970-01-01
        • 2018-11-23
        • 2010-11-14
        • 1970-01-01
        • 2021-03-31
        相关资源
        最近更新 更多