1

SOにはこれらの質問が散らばっていることを認識しており、多くのことを見てきました。

私は現在、C++ を使用して学校のプロジェクト用に逆アセンブラーを作成しています。メイク ファイルを実行すると、シンボルの重複エラーが発生します。私の問題は、上記の例よりも少し複雑ではないかと思います。質問が重複して申し訳ありませんが、何時間も検索して問題を解決しようとしてもわかりません。建設的で完全で肯定的なフィードバックをいただければ幸いです。

  • g++バージョン 3.4.6 (はい、古いです – 学校のサーバー)
  • makeバージョン 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;
}
4

2 に答える 2

2

この行optab.hは問題です:

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

.cppこの .h ファイルを含むすべてのファイルは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変数にして、1 つのファイルだけで定義し.cppます。

  2. それらをstatic変数にすることによって。

  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 = ...;
    
于 2015-04-20T05:02:04.783 に答える
0

これは「重複シンボル cerr」の Google での最初の結果だったので、ここで回答すると役立つと思います。

-fcommon新しい gcc/clang (v10、v11) バージョンは、デフォルトでシンボルの重複に対してより厳密ですが、この動作はフラグで調整できます

clang main.c -fcommon
于 2020-12-09T17:32:08.567 に答える