【问题标题】:Why do I get a multiple definition error while linking?为什么在链接时出现多重定义错误?
【发布时间】:2012-04-15 02:49:39
【问题描述】:

我使用herehere这两个文件。

我在两个单独的文件中创建了一个类:

模块1.h

#ifndef MODUL1_H
#define MODUL1_H

#include <iostream>
#include <fstream>

#include "easylogger.h"

class Modul1
{
    public:
        Modul1(std::string name);
    protected:
    private:
        easylogger::Logger *log;
};

#endif // MODUL1_H

和 modul1.cpp

#include "modul1.h"

Modul1::Modul1(std::string name):log(new easylogger::Logger(name))
{
    //ctor
    //std::ofstream *f = new std::ofstream(name.c_str(), std::ios_base::app);
    //log->Stream(*f);
    //log->Level(easylogger::LEVEL_DEBUG);
    //LOG_DEBUG(*log, "ctor ende!");
}

现在我想在另一个文件(main.cpp)中使用这个类:

#include "modul1.h"

int main()
{
    std::cout << "Hello world!" << std::endl;
    Modul1 mod1("test.log");
    return 0;
}

当我使用以下 Makefile 编译它时,我得到一个“...的多重定义”错误:

g++ main.o modul1.o -o main
modul1.o: 在函数easylogger::Logger::Format(std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; const&amp;):
modul1.cpp:(.text+0x0): 多重定义 easylogger::Logger::Format(std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; const&amp;)
main.o:main.cpp:(.text+0x0): 首先在这里定义
modul1.o:在函数easylogger::Logger::WriteLog(easylogger::LogLevel, easylogger::Logger*, char const*, unsigned int, char const*, char const*): modul1.cpp:(.text+0x2a): 多重定义 easylogger::Logger::WriteLog(easylogger::LogLevel, easylogger::Logger*, char const*, unsigned int, char const*, char const*)
main.o:main.cpp:(.text+0x2a): 首先在这里定义
collect2: ld 返回 1 个退出状态

(一开始我用code::blocks编译,还是一样的错误)

如何修改我的 Modul1 以免出现此链接错误?我认为这并不重要,但我正在使用一些带有 g++ 4.4.3 的 Ubuntu 64 位

生成文件:

CC=g++
CFLAGS=-c -Wall

all: log_test

log_test: main.o easylogger.h modul1.o
    $(CC) main.o modul1.o -o main

main.o: main.cpp modul1.h
    $(CC) $(CFLAGS) main.cpp

modul1.o: modul1.cpp modul1.h
    $(CC) $(CFLAGS) modul1.cpp

【问题讨论】:

  • 为什么要写一整页而不贴出完整的错误信息?
  • 多重定义...什么?这里的“什么”是最重要的部分。
  • 还有,为什么main.o会引用modul1.cpp?
  • 试图改进错误信息的显示:请检查!

标签: c++ ubuntu linker gcc4.4


【解决方案1】:

按照您构建它的方式,easylogger.h(以及随之而来的 easylogger-inl.h)被包含两次,一次用于 modul1.h,一次用于 main.cpp

你的用法是错误的。但是您可以这样做以使其正常工作:

在 modul1.h 中(去掉#include "easylogger.h"),让它看起来像这样

#ifndef MODUL1_H
#define MODUL1_H

#include <iostream>
#include <fstream>
//#include "easylogger.h"

namespace easylogger { class Logger; };

class Modul1
{
    public:
        Modul1(std::string name);
    protected:
    private:
        easylogger::Logger *log;
};

#endif // MODUL1_H

对于 modul1.cpp,包括真实的东西

#include "modul1.h"
#include "easylogger.h"

Modul1::Modul1(std::string name):log(new easylogger::Logger(name))
{
    //ctor
    //std::ofstream *f = new std::ofstream(name.c_str(), std::ios_base::app);
    //log->Stream(*f);
    //log->Level(easylogger::LEVEL_DEBUG);
    //LOG_DEBUG(*log, "ctor ende!");
}

祝你好运!

【讨论】:

    【解决方案2】:

    您在两个翻译单元中都包含“easylogger-impl.h”。 easylogger-impl.h 中有函数定义。因此,您的函数有多个定义。

    一个定义规则是说你必须有一个,而且只有一个,任何对象或函数的定义。

    您可以通过将所有 easylogger-impl 函数标记为 inline 或确保它们仅出现在一个翻译单元中来解决此问题。

    【讨论】:

    • 好的,使“错误”函数内联有效,但我必须修改其他人的代码。如何确保 easylogger-impl 函数只出现在一个翻译单元中?
    【解决方案3】:

    这不是针对您的特定情况的解决方案,但我会为其他找到此主题的人提及它,因为它可能会产生相同的错误。

    如果您正在运行编译器,并忽略-o 标志,并且二进制文件的副本已经存在,编译器将尝试将新目标文件与该二进制文件链接。新的目标文件和它的二进制文件都有自己的main 和各种其他符号,并给你关于它们的警告。

    > g++ MyTest.cxx -g MyTest -I.
    /usr/bin/ld: MyTest: in function `main':
    /t/proj/MyTest/MyTest.cxx:172: multiple definition of `main'; /tmp/cccYfx2V.o:/t/proj/MyTest/MyTest.cxx:172: first defined here
    :
    :
    :
    collect2: error: ld returned 1 exit status
    > g++ MyTest.cxx -g -o MyTest -I.
    >
    

    注意第二个命令有-o 选项,并且没有注释就成功了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-22
      相关资源
      最近更新 更多