鍍金池/ 問(wèn)答/C++  Linux  網(wǎng)絡(luò)安全/ g++ 鏈接 變量被多次定義?

g++ 鏈接 變量被多次定義?

這是map_test.h文件

#ifndef _MAP_TEST_H
#define _MAP_TEST_H

#include <map>
#include <string>

using std::map;
using std::string;

map<string, string> map_config;

void init_map_config();

#endif

這是map_test.cpp文件

#include "map_test.h"

void init_map_config()
{
    map_config.insert({"123", "123"});
    map_config.insert({"456", "456"});
    map_config.insert({"789", "789"});
}

這是main.cpp文件

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

using std::cout;
using std::endl;

int main()
{
    init_map_config();

    for (auto it = map_config.begin(); it != map_config.end(); it++)
        cout << it->first << " " << it->second << endl;
    cout << endl;
}

編譯:
g++ -c map_test.cpp -o map.o -std=c++11
g++ -c main.cpp -o main.o -std=c++11
編譯都是成功的,鏈接過(guò)程出錯(cuò):
g++ map.o main.o -o main
此時(shí)出錯(cuò):

main_test.o:(.bss+0x0): `map_config'被多次定義
map_test.o:(.bss+0x0):第一次在此定義
collect2: error: ld returned 1 exit status

為什么會(huì)報(bào)錯(cuò)?

回答
編輯回答
魚梓

1,在map_test.cpp文件中定義map<string, string> map_config;
2,在map_test.h中使用extern map<string, string> map_config;

2018年6月21日 11:47
編輯回答
黑與白

變量和函數(shù)的定義 , 都應(yīng)該放在cpp文件中, 否則很容易產(chǎn)生多重定義.
為什么呢?
因?yàn)閏++的編譯單位是cpp文件. 如果這個(gè)頭文件被多個(gè)cpp包含了, 那么這個(gè)頭文件中的定義的變量或者 函數(shù)就會(huì)在這些cpp生成的obj中存在, 在鏈接的時(shí)候, 就會(huì)發(fā)現(xiàn)多個(gè)obj存在同一個(gè)變量或者函數(shù)實(shí)現(xiàn), 自然就會(huì)報(bào)重定義了.

所以:
除非你能清楚的知道, 這個(gè)頭文件只會(huì)被一個(gè)cpp文件包含一次. 那么放到頭文件中沒(méi)有問(wèn)題.
如果不確定, 那么變量定義或者函數(shù)的實(shí)現(xiàn), 就老實(shí)的放到.cpp文件中吧.

可能你要問(wèn), 變量放到.cpp中的, 那么其它文件中如何使用它呢?
答案是使用聲明: extern
比如: extern map<string, string> map_config;

2017年5月27日 05:33
編輯回答
傻叼

因?yàn)檫`背了ODR。map_config定義在頭文件中,并且是外部鏈接。這個(gè)頭文件分別被兩個(gè)源文件包含,這導(dǎo)致鏈接時(shí)map_config在兩個(gè)目標(biāo)文件中有定義。

解決方案是將定義移到源文件中,在頭文件中只留下純聲明。

2017年8月26日 15:16
編輯回答
凹凸曼

有兩種解決辦法

  1. 在頭文件中使用extern聲明,在源文件中定義

  2. 將map<string, string> map_config和函數(shù)init_map_config都定義為static

2018年9月23日 14:56