Why does global variables in a header file cause l

2019-01-28 17:11发布

I always get the following error, even if I have put include guard in header file.

duplicate symbol _Bittorrent in:
    /Users/tracking/Library/Developer/Xcode/DerivedData/SHT-giuwkwyqonghabcqbvbwpucmavvg/Build/Intermediates/SHT.build/Debug/SHT.build/Objects-normal/x86_64/main.o
    /Users/tracking/Library/Developer/Xcode/DerivedData/SHT-giuwkwyqonghabcqbvbwpucmavvg/Build/Intermediates/SHT.build/Debug/SHT.build/Objects-normal/x86_64/Handshake.o
duplicate symbol _eight_byte in:
    /Users/tracking/Library/Developer/Xcode/DerivedData/SHT-giuwkwyqonghabcqbvbwpucmavvg/Build/Intermediates/SHT.build/Debug/SHT.build/Objects-normal/x86_64/main.o
    /Users/tracking/Library/Developer/Xcode/DerivedData/SHT-giuwkwyqonghabcqbvbwpucmavvg/Build/Intermediates/SHT.build/Debug/SHT.build/Objects-normal/x86_64/Handshake.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Here are .h header file, .c file, and main.c

main.c

#include "Handshake.h"
int main(int argc, char** argv)
{
    // some code.
    return 0;
}

Handshake.h

#ifndef SHT_Handshake_h
#define SHT_Handshake_h

const char    *Bittorrent     =   "BitTorrent protocol";
const char    eight_byte[8]   =   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

#endif

Handshake.c

#include "Handshake.h"


int Send_fisrt_Handshake(download_connection *pPeer, Handshake *necessary_info)
{
    //some statements
    return 1;
}

void Set_Handshake_information(TorrentFile* pArg, Handshake *pYours)
{

    //some statements

}

But, If I deleted global variables from header file, these codes compile successfully.
I don't understand why. Could someone explain why? Thank you in advance.

5条回答
贼婆χ
2楼-- · 2019-01-28 17:54

Lines like

const char    *Bittorrent     =   "BitTorrent protocol";
const char    eight_byte[8]   =   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

define theses global variables no matter if that codes is in header file or ine a .c directly (#include is just textual insertion of the header's contents). Instead you should have the definitions in exaclty one source file and change the header to provide an extern declaration instead:

extern const char *Bittorrent;
extern const char *eight_byte;

Then all your sources using thes variables can be compiled but the linker will the variables once only.

查看更多
霸刀☆藐视天下
3楼-- · 2019-01-28 17:55

Also note that you have a typo.

Send_fisrt_Handshake instead of Send_first_Handshake.

I can imagine that you simply mistyped it into your question. But you never know; typos can be hard to find and fix in large code. :)

查看更多
Luminary・发光体
4楼-- · 2019-01-28 17:58

Because you define the variables in the header file. Then all source files that includes the header file will have those variables defined.

You can declare the variables, using the extern keyword:

extern const char    *Bittorrent;
extern const char    eight_byte[8];

And then in one source file define the variables.

Or you could define the variables as static, which limits their scope to the translation unit (i.e. source file):

static const char    *Bittorrent     =   "BitTorrent protocol";
static const char    eight_byte[8]   =   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

This is different from C++, where const also implies static.

查看更多
太酷不给撩
5楼-- · 2019-01-28 18:03

By initializing the variable, you are defining it in every place that the file is included. Assuming that these modules are linked together, you now have multiple definitions, which is an error.

You can declare the variable in your header with an extern tag and then initialize it in one of your .c modules.

In your .h file:

extern int i;

In one of your .c files:

int i = 1;

However,

查看更多
小情绪 Triste *
6楼-- · 2019-01-28 18:15

Header:

extern const char    *Bittorrent;

Main (before the main function / as gloabal variable):

const char    *Bittorrent     =   "BitTorrent protocol";

This way your header tells every file that there is variable named "Bittorrent", but only your main.c file has the part in it where it is really created.

查看更多
登录 后发表回答