【问题标题】:Duplicate Symbol in CC中的重复符号
【发布时间】:2011-10-03 18:10:52
【问题描述】:

我有两个源文件:

源文件 1 (assembler.c):

#include "parser.c"
int main() {
    parse_file("test.txt");
    return 0;
}

源文件 2 (parser.c):

void parse_file(char *config_file);
void parse_file(char *src_file) {
    // Function here
}

由于某种原因,编译时出现以下错误: duplicate symbol _parse_file in ./parser.o and ./assembler.o for architecture x86_64

为什么它给了我一个重复的 parse_file 符号?我只是在这里调用函数...不是吗?

【问题讨论】:

  • C 中没有类......只是一个挑剔的问题:你的措辞。
  • 那么当你在“吹毛求疵”时,为什么不建议使用“模块”、“源文件”或“翻译单元”这些术语呢?

标签: c function duplicate-symbol


【解决方案1】:

首先,在 C 编程中包含源文件是一种不好的做法。通常,当前翻译单元应该由一个源文件和多个包含的头文件组成。

在您的情况下,您有两个 parse_file 函数副本,每个翻译单元中都有一个。 parser.c编译成目标文件时,有自己的parse_file函数,assembler.c也有自己的。

当给定两个目标文件作为输入时,抱怨的是链接器(而不是编译器),每个目标文件都包含自己的 parse_file 定义。

你应该像这样重组你的项目:

parser.h

void parse_file(char *);

parser.c

void parse_file(char *src_file) {
    // Function here
}

assembler.c

/* note that the header file is included here */
#include "parser.h"

int main (void) {
    parse_file("test.txt");
    return 0;
}

【讨论】:

    【解决方案2】:

    您将包含 parser.c 文件,这意味着该文件中的所有代码都将“复制”到 assembler.c 文件中。也就是说,编译器在编译parser.c的时候会编译parser.c的全部内容,然后编译器编译assembler.c的时候再编译一遍

    这就是标题的用途。
    在标题中您只能放置声明,因此您可以包含它而无需在不同的翻译单元中再次创建相同的符号。

    所以您可以创建一个仅包含函数声明的 parser.h:

    void parse_file(char *config_file);
    

    然后在您的 assembler.c 中只包含标题:

    #include "parser.h" //include the header, not the implementation
    int main() {
        parse_file("test.txt");
        return 0;
    }
    

    【讨论】:

    • 你肯定想要一个“parser.h”作为你的函数原型和任何类型定义。您还需要一个“守卫”,例如“#ifndef PARSER_H #define PARSER_H ... #endif /* PARSER_H */
    • PS:filipe(以及片刻之后,Blagovest Buyukliev)正在为您提供“解决方案”。 David Heffernan 解释了为什么需要该解决方案。 PPS:不要忘记“#ifndef”守卫;)!您可能还想添加“extern "C" {}"。
    • 是的,我知道这一点。我完全忘记了这一点,因为我已经快一年没学过 C 语言了。我知道我应该做什么。谢谢!
    【解决方案3】:

    您将包含 .c 文件,其中包含函数 parse_file 的定义。因此它被定义了两次,每个翻译单元一次,这是不允许的。

    【讨论】:

      【解决方案4】:

      正如其他答案所述,包括源意味着文件将被复制到 parser.c 并在原始位置(assembler.c )。要解决这个问题,请使用您的原型创建一个头文件:

      解析器.h

      void parse_file(char *config_file);
      

      并包含那个文件:

      汇编程序.c

      #include "parser.h"
      int main() {
          parse_file("test.txt");
          return 0;
      }
      

      或者删除包含并提供函数的线索:

      int main() {
          void parse_file(char *);
          parse_file("test.txt");
          return 0;
      }
      

      或者甚至简单地删除包含在 al。不好的做法,因为编译器(没有函数信息)会认为它的返回值是一个整数,并可能导致其他警告。

      【讨论】:

        猜你喜欢
        • 2015-07-08
        • 2014-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-06
        • 2013-07-05
        • 2018-02-20
        • 1970-01-01
        相关资源
        最近更新 更多