c++ - Makefile 重复符号

标签 c++ makefile g++ duplicate-symbol

我想花点时间说一下,我知道 SO 充斥着这些问题,我已经看过很多:

我目前正在使用 C++ 为一个学校项目构建一个反汇编程序,当我运行我的 make 文件时,我遇到了重复符号错误。我担心我的问题比上面引用的例子要复杂一些。对于重复的问题,我深表歉意,但经过数小时的搜索和尝试解决问题后我无法弄清楚,我感谢任何人提供的任何建设性、完整和积极的反馈。

  • g++ 版本 3.4.6(是的,我知道,它很旧 – 学校服务器)
  • 制作版本 3.81

这是我的生成文件:

CC=g++
CFLAGS=-Wall -O0 -c

all: dasm

dasm: main.o optab.o record_tokenizer.o regex.o
    $(CC) -o $@ $^

clean:
    rm *.o dasm

看起来 Make 能够将所有文件转换为它们各自的目标文件,但是链接到单个可执行文件是失败的:

c++    -c -o main.o main.cpp
c++    -c -o optab.o optab.cpp
c++    -c -o record_tokenizer.o record_tokenizer.cpp
c++    -c -o regex.o regex.cpp
g++ -o dasm main.o optab.o record_tokenizer.o regex.o
duplicate symbol _optab in:
    main.o
    optab.o
duplicate symbol _optab in:
    main.o
    record_tokenizer.o
duplicate symbol _HEADER_RECORD_REGEX in:
    main.o
    record_tokenizer.o
duplicate symbol _END_RECORD_REGEX in:
    main.o
    record_tokenizer.o
duplicate symbol _TEXT_RECORD_REGEX in:
    main.o
    record_tokenizer.o
duplicate symbol _MOD_RECORD_REGEX in:
    main.o
    record_tokenizer.o
ld: 6 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [dasm] Error 1

我绝对不是 C++ 专家,也不是 Makefile 专家,因此非常感谢您的帮助。以下是相关文件:

optab.h

#ifndef __dasm__optab__
#define __dasm__optab__

#include <map>
#include <string>

std::map<short, const char*> optab;

void init_optab();
const char* get_instruction(int n);

#endif

正则表达式.h

#ifndef __dasm__regex__
#define __dasm__regex__

#include <regex.h>

bool match(const char* pattern, const char* string);

#endif

record_tokenizer.h

#ifndef __dasm__record_tokenizer__
#define __dasm__record_tokenizer__

#include <vector>
#include <cstdlib>
#include <sstream>
#include "regex.h"
#include "optab.h"

const char* HEADER_RECORD_REGEX = "^H[a-zA-Z|[:space:]]{6}[:digit:]{12}";
const char* END_RECORD_REGEX = "^E([:digit:]{6})?";
const char* TEXT_RECORD_REGEX = "^T[:digit:]{6}[0-1][0-E][:digit:]{,60}"; // TODO: improve on this
const char* MOD_RECORD_REGEX = "^M[:digit:]{8}";

struct Record {
    char record_type;
    std::string name;
    std::string address;
    std::vector<std::string> addresses; // used for T records only
};


bool is_valid_record(const char* record, const char* pattern);
const int to_i(std::string n);
const Record tokenize_record(std::string record);

#endif

main.cpp

#include <iostream>
#include "record_tokenizer.h"

using namespace std;

int main(int args, const char* argv[]) {
    if(args > 2) {
        std::cerr << "Usage: dasm sample.obj" << std::endl;
        exit(EXIT_FAILURE);
    }
    tokenize_record("T0000001E^050000^032003^3F^69101791^1BA0131BC0002F200A3B2FF40F102F014F0000");

    return 0;
}

最佳答案

optab.h 中的这一行是一个问题:

std::map<short, const char*> optab;

包含此 .h 文件的每个 .cpp 文件都将 optab 定义为全局变量。这将导致多次定义该符号。

相同的错误将由行产生:

const char* HEADER_RECORD_REGEX = "^H[a-zA-Z|[:space:]]{6}[:digit:]{12}";
const char* END_RECORD_REGEX = "^E([:digit:]{6})?";
const char* TEXT_RECORD_REGEX = "^T[:digit:]{6}[0-1][0-E][:digit:]{,60}";
const char* MOD_RECORD_REGEX = "^M[:digit:]{8}";

record_tokenizer.h 中。

您可以通过以下方式修复它们:

  1. 通过使它们成为extern 变量并仅在一个.cpp 文件中定义它们。

  2. 通过使它们成为静态变量。

  3. 通过使它们成为const。这适用于字符串,但不适用于 optab。我想您需要更改它的值。

    const char* const HEADER_RECORD_REGEX =  ...;
    const char* const END_RECORD_REGEX = ...;
    const char* const TEXT_RECORD_REGEX = ...;
    const char* const MOD_RECORD_REGEX = ...;
    

关于c++ - Makefile 重复符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29739510/

相关文章:

c++ - 与 gcc、g++ 和 gfortran 链接

c++ - avr-g++ 使用 c++ 代码生成错误

c++ - 在 C++ 中, “throw” 和 “throw ex” 之间有区别吗?

python - 在 python 中调用 C 库?

makefile - 如何在 makefile 中指定 RPATH?

c++ - 如何编译依赖于 C++ 目标文件的 CUDA 共享库?

c++ - 从另一个 .cpp 文件调用 cpp 函数时出错

c++ - Visual C++ 2013、TFS 和属性表的问题

c - make如何自动创建.o文件

linux - 生成文件 g++ : fatal error: no input files