4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

起こらないはずの duplicate symbolが起こったときの対処法(備忘録)

Last updated at Posted at 2021-05-14

問題

以下のようなコードがあり、コンパイルしてみる

Main.cpp
# include "Main.h"
...
Main.h
# pragma once
int f(int a){
    ...
}
hoge.cpp
# include "hoge.h"
...
hoge.h
# pragma once
# include "Main.h"
...

そうすると、あるエラーが。(多少パスは省略)

duplicate symbol 'f(int)' in:
    .../Main.o
    .../hoge.o
ld: 1 duplicate symbol for architecture x86_64

どうやら、f(int a)がMain.hとhoge.hで二重で定義されているようだ。

...ん?
確か、しっかりとMain.hに#pragma onceはついてるが...

解決法

関数の定義にstaticを追加したら直った(こんな感じ)
追記:
staticではなくinlineを使った方がいいらしい。
staticは定義の区別で、inlineは重複定義の許容なので、inlineを使った方が軽くなるとのこと
@makia さんthanks!

Main.h
# pragma once
inline int f(int a){
    ...
}

なんでかはわからないけど、なんでだろう

原因

@tenmyo さんthanks!
まず、エラーが出ているのはコンパイルではなくそのあとのリンクの時に出ていた。
確かに、#pragma onceで重複は防いでいたが、それは「コンパイル時のソースコードの重複」を防いでいただけでその後のリンク時には関係していない。
つまり、コンパイル時に生成されたmain.ohoge.oの両方にf(int a)が定義されて、そこまではよかったけど、いざリンクするとなった時に同じ定義が出てきてエラー。と言った流れ

そこで、inlineで重複定義を許容することで解決する

4
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?