VC PlusPlus:Link Error LINK2019 未解決のシンボル…で参照されました。 対処方法のソースを表示
新しいページはコチラ
移動:
案内
,
検索
[[VC PlusPlus]]に戻る == '''概要''' == Visual Studioを使うプログラマなら、一度は目にするエラーです。他人が作ったプロジェクトとか複雑なプロジェクトになれば、その遭遇率は高くなります。 これは、基本的にあなたの落ち度ではない事が多いのです。落胆しないで!自分で全てコーディングしたのにリンカエラーが出る場合は、自分の責任ですので、軽く自分の指に針を刺すなりして戒めていただければと思います。自分で自分を罰するというのは刺激的ですよ。アイスでも食べて頭を冷やして、甘やかしてもいいですけど。 対処方法はいくつかのパターンに分かれています。解決が困難なモノもあります。他人のやることなのでね。簡単な対処方法が提供されていないとかあるよ。それでも乗り越えて行く力(チカラ)はあった方がいい。いかなる場合でも冷静に全ての整合性をとるということは、有能なプログラマである証拠だ。 簡単ではないいくつかのパターンについて、ココで一緒に考えていきましょう。 === ''' 知っていた方が良い知識 ''' === '''1.切り分けという概念''' Libファイルを使うということは、よくわからない何かと結びつけることもあると思いますが、わからないなりに守っておくべきことがあります。考えすぎになってしまうこともありますが、32bit版でコンパイルするプログラムには32bit版の*.libファイルを、64bit版でコンパイルするプログラムでは64bit版の*.libファイルを用意するようにしましょう。ライブラリ側の作りによっては意識する必要がない場合もあります。 そして、Debug版とRelease版もわけるべきです。例えば良く使われるマイクロソフトのC言語ランタイムライブラリでは、msvcrt.libという名前ですがデバッグ版はmsvcrtd.libという名前になっていたりします。Release版のライブラリ名のどこかにdを付け足すのが一般的です。おそらくDebugのdです。Debug版のライブラリって何?って感じですが、Debugという作業を開発環境で実施する場合は、作った関数やプログラムにDebug用のプログラムが一緒に生成されることで実現されています。読み込んだライブラリに対しても、1行づつプログラムを動かして追いかけるにはライブラリがDebug版として生成されたものである必要があります。違っていると必ずDebug版のライブラリを参照する仕組みになっている部分があるとリンクエラーになることもあります。Release版は容量が軽くて便利ですが、細かいDebugはできないです。ライブラリがReleaseであっても一行づつ追うことを諦める覚悟ならデバッグは出来ますが、Debug版でなければ動作しないこともあります。 どこかから入手したオープンソースをビルドする場合、プロジェクトのプロパティ(コンパイルリンク処理のオプション引数)を見て、必要としているライブラリが記述されている場合があります。頑張って全部入手できなければ、そのオープンソースソフトウェアをビルドすることは出来ません。オープンソースだからといって、簡単にビルドできるとは限らない事を知っておきましょう。人のプログラムをビルドするだけのことでも、とんでもなく大変な作業になったりすることがあるという覚悟が必要です。手取り足取り、全ての手順をオープンソースプロジェクトの開発者が提供しているWebsiteになっているとは限りません。 === ''' 知っていた方が良い小技 ''' === '''1.Lib/Dllの中の関数を知る''' Lib/Dllファイルに目的の関数が格納されているかを確認する方法があるので、この方法を知っておいた方が良いでしょう。 以下のようなコマンドを使います <syntaxhighlight2 lang="bash"> dumpbin.exe /LINKERMEMBER (ライブラリファイル名or(完全パスor相対パス)\ライブラリファイル名) </syntaxhighlight2> dumbinは、C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\bin\Hostx86\x86のようなパスの元にあるものが使われます。このようなコマンドを使う場合は、VisualStudioのメニュー[ツール]-[コマンドライン]-[開発者用PowerShell]から起動すると、パスがとおった状態のPowerShellのコマンドプロンプトが立ち上がります。このようにして起動した場合は単にdumpbinとするだけでコマンドが使えます。 静的なライブラリ*.LibファイルはLINK処理の時点でエラーが出ますので、LINKERエラーは主にコチラの修正や確認作業が発生することでしょう。動的なライブラリ*.Dllはアプリを使っている時に発生するエラーになります。いずれにせよ、対応する関数がライブラリの中になかったら動きません。 上記コマンドで、Lib・Dllファイルに格納される関数名が一覧できます。まずは読み込んでいるLibの中身に関数が本当に無いのか確認してみるのも良いでしょう。そうすれば、読み込み設定の問題ではなく、新たなライブラリの欠落やライブラリの中に必要な関数が格納されていない間違ったライブラリになっていることが原因だと考えることができます。 '''2.Dll→LibのようなLib半自動生成の手順''' 以下のようなコマンドを打つと生成できます。必ずしも出力できるわけではありません。dllを生成したプログラム側で__declspec(dllexport)というような宣言をしてあるものに限ります。 <syntaxhighlight2 lang="bash"> dumpbin.exe /EXPORT (DLLライブラリファイル名or(完全パスor相対パス)\DLLライブラリファイル名) > (ライブラリ名と同じ名前).def lib /DEF:(ライブラリ名).def /MACHINE:X86 /out:(ライブラリ名).lib </syntaxhighlight2> とします。Export可能な関数がなければエラーになります。あるといいね。 '''3.パスが通っているか確認する''' きちんとLibを読み込んでいるつもりでも、環境変数のPathが通っていなくて、うまくいっていないことも多いです。そんなときは以下のようなコマンドでファイルが参照できるか試してみましょう。パワーシェルではなく、コマンドプロンプトが良いでしょう。 <syntaxhighlight2 lang="bash"> >where (ファイル名) パス名\ファイル名 </syntaxhighlight2> パスが通っていてファイルがある場合はコマンドを確定した後に、そのファイルへの完全パスが表示されます。 whereコマンドはオプションによっては特定のフォルダでの検索や、特定のフォルダ+サブフォルダでの検索といった検索もできますが、オプションを指定しない場合は、現在のディレクトリと環境変数のパスの中を検索してくれます。ファイル名にはワイルドカード * や ? が使えます。 上記検索に加えてさらにもっと正確な検索をします。ライブラリディレクトリと追加のライブラリディレクトリというのをVisualStudioでは設定できるようになっていて、このパスの中に所定のlibファイルがあるかを検索します。ライブラリのディレクトリは、メニューの[プロジェクト]-[プロパティ]から[構成プロパティ]-[VC++ディレクトリ]にある[ライブラリディレクトリ]という設定のパスと[構成プロパティ]-[リンカ]-[追加のライブラリディレクト]に設定されているものです。$(xxx)とかっていうパスの場合は展開する必要がありますので、パス設定を選択して表示される[編集]を選択するとダイアログが起動します。評価された値というのが実際に検索されるパスです。変数では表現されていないので、扱い易いはずです。改行を \n を ; に変換するできるテキストエディタがあると、検索用のパス名を作りやすいです。 <syntaxhighlight2 lang="bash"> >where /R "(パス名)" (ファイル名) パス名\ファイル名 </syntaxhighlight2> (パス名)で複数を指定したい場合は ; セミコロンで区切って複数指定することが出来ます。 パスが通っていない場合、パスを追加すると思いますが、なるべく相対パスを使うと良いでしょう。パスの基点はプロジェクト(*.vcxproj)ファイルの置かれているところからのパスになります。 === ''' 対処方法 ''' === '''1.安全ではない古い関数が使われるパターン''' scanf, printf, strlen, strcmpといったC言語の基本とも言える関数を使ったときに発生します。昨今ではオーバーフローしないような、より安全な関数を使うのが定説になっていますが、勉強のため、ためしにgccとか古いVisual Studioで主に開発しているプログラマからプログラムをもらってきたときとかに発生します。古い関数自体は新しいVisual Studioでもコンパイルできるので、関数は新たにobjファイル化することが出来て問題なく使えます。これがlibファイル化された中で呼び出して、使われている場合です。この場合、他のlibファイルの中で古い関数が提供されている必要があり、リンカ設定をしておかないと駄目です。Visual Studioで最初から設定されているリンカ設定されているlibファイルからは、古い関数が消えています。つまり、参照先が無い。リンクエラーだよ。ってなります。なんで、こんな嫌がらせするのか?と思ってしまいますが、Micorsoftは昔ながらの関数群を標準ヘッダファイルでインライン定義(ヘッダファイルの中に関数の定義をして、ついでにプログラムの内容までヘッダファイルに記述する方法です)して内部で持たせるように変更したかったようです。libファイルによる外部ファイル参照を必要としない方法で扱いたかったんすかね。ナカナカ思い切った互換性を保たない変更です。 プログラマを悩ませる変更をするなんて、アホかと馬鹿かと、愚痴ってもしょうがないです。こういう変更に敏感に対応できてこそプログラマたるプログラマなのだと突き進むしかないのです。 メンドクサイ対応方法としては、入手したlibのソースファイルがあれば、それを入手してすべての関数をscanf_sのような最新のMSVC(MicrosoftVisualCpp)の標準libで提供されている関数を使ってlibファイルを再構築するのがいいのですが、scanf_sに変えて、受け取る文字列のサイズを調整するという作業をすべての基本関数に対して施術しなくてはなりません。それが割かし膨大なプロジェクトである場合、とてもじゃないけど、修正しきれないし、どんなに有能なプログラマでも何度も繰り返して同じことをやるだけにしても、どこかでミスタイプや、計算間違えでバグを起こす原因にもなります。それにそもそもソースが提供されている場合に限ります。 そんな時は旧型対応のライブラリを使いましょう。 *旧型のライブラリを使用して解決! :対処したいプロジェクトをアクティブにした状態で、メニューの[プロジェクト]-[プロパティ]を選択して表示されるダイアログで[構成プロパティ]-[リンカ]-[入力]の[追加の依存ファイル]に ::'''legacy_stdio_definitions.lib''' :を追加します。なんだ、あるんじゃん。古い関数が使われたら、自動的にリンクしろよ。って思ったりもします。でも、本当に古い関数をそのまま使うかはプログラマ側で判断すべし!とMicrosoftは言っています。 続きはまた気が向いたら書くので記事は増えていく予定。 [[VC PlusPlus]]に戻る
VC PlusPlus:Link Error LINK2019 未解決のシンボル…で参照されました。 対処方法
に戻る。
個人用ツール
ログイン
名前空間
ページ
議論
変種
表示
閲覧
ソースを表示
履歴表示
操作
検索
案内
メインページ
コミュニティ・ポータル
最近の出来事
最近の更新
おまかせ表示
ヘルプ
ツールボックス
リンク元
関連ページの更新状況
特別ページ