0
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?

MinGWのg++でコンパイルしたstd::coutを含むプログラムが落ちる

Last updated at Posted at 2025-05-10

std::coutを使うと落ちる

2年前くらいから、Mingw-w64のg++でコンパイルしたプログラムが実行できない(数秒フリーズ後何も出力せず終了)することに気が付きました。
例えば、以下に示すようなプログラムが動きませんでした。

test.cpp
#include <iostream>
int main() {
  int a = 10;
  std::cout << a << std::endl;
  return 0;
}

これをg++ test.cppでコンパイルした実行可能ファイルが落ちます。
色々試してみると、printfを使ったプログラムなら問題なく動作することが分かりました。

#include <iostream>
int main() {
  int a = 10;
  printf("%d\n", a);
  return 0;
}

これに気づいた当初は焦りましたが、そこまでWindowsでg++を使わなかったので大きな問題にはならず、調査も面倒だったので何かの拍子に直ることを期待して放置対応を後回しにしていましたが、重い腰を上げて直すことにしました。

静的リンクを試す

この問題について調べていると、12年前に似たような問題が発生した記事を発見したので、この記事の流れに沿って進めていきました。
まず、g++自体がおかしいのか確認するため、静的リンクでコンパイルしてみました。g++ test.cpp -staticで共有ライブラリとのリンクを抑止してビルドを行うと、正しく標準出力されたのでg++自体がおかしいわけではなさそうです。
ところで、実行可能ファイルがどの共有ライブラリ(DLL)に依存しているかはdumpbinコマンドで調べることができます1

$ dumpbin /DEPENDENTS a.exe
Microsoft (R) COFF/PE Dumper Version 14.29.30151.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file a.exe

File Type: EXECUTABLE IMAGE

  Image has the following dependencies:

    libstdc++-6.dll
    KERNEL32.dll
    msvcrt.dll

  Summary

        1000 .CRT
        1000 .bss
        1000 .data
        1000 .debug_abbrev
        1000 .debug_aranges
        1000 .debug_frame
        1000 .debug_info
        1000 .debug_line
        1000 .debug_line_str
        1000 .debug_str
        1000 .eh_frame
        1000 .idata
        1000 .pdata
        1000 .rdata
        1000 .reloc
        2000 .text
        1000 .tls
        1000 .xdata

-staticオプションを付けずにコンパイルした実行可能ファイルで試した結果によると、C++は3つの共有ライブラリに依存していることが分かります。
coutを使うと落ちることから、この中ではC++標準ライブラリの定義であるlibstdc++-6.dllが怪しいです(実際printfを使って標準出力を行うと、libstdc++-6.dllには依存しなくなるため、このDLLの読み込みに問題が生じていそうです)。
g++ test.cpp -static-libstdc++で、libstdc++-6.dllについて静的リンクするようにすると、正しく標準出力されるようになったため、実行時のDLL読み込みがうまく行っていないことが分かりました。

DLLの検索順序

本来はg++と同じディレクトリ上のDLLが読み込まれるべきですが、別のものが読み込まれて落ちる状況が発生しています2。そのため、どのような流れでDLLが読まれているのかを知る必要がありました。
実行時のDLL検索順序はどうなっているのでしょう。
調べてみると以下のような順序で決まることが分かりました。

  1. アプリケーションのexeファイルが存在するディレクトリ
  2. SYSTEMディレクトリ
  3. カレントディレクトリ
  4. 環境変数PATHで設定されたディレクトリ

これを踏まえて、どのようにlibstdc++-6.dllが検索されるかを調べてみます。

  1. アプリケーションのexeファイルが存在するディレクトリ
    libstdc++-6.dllは存在しません
  2. SYSTEMディレクトリ(%WINDIR%\System, %WINDIR%\System32)
    libstdc++-6.dllは存在しません
  3. カレントディレクトリ
    今回、exeファイルのディレクトリとカレントディレクトリは同じなので、libstdc++-6.dllは存在しません
  4. 環境変数PATHで設定されたディレクトリ(%PATH%)
    C:\anaconda3\Library\mingw-w64\binlibstdc++-6.dllを発見

上記の流れでlibstdc++-6.dllが発見されて、読み込まれるようです。これは本来読み込まれるべきDLLではないので、結果落ちたということになります。

Anacondaはかなり前からインストールしていたものの、PATHを通したのは後からだったので気づかず、今回の問題が発生していたということでしょう。

対処法

  • Anadondaを削除する
  • AnacondaのPATHを変える

今回はとりあえず問題となっているC:\anaconda3\Library\mingw-w64\binを含むAnacondaのPATH優先順位を下げることで対応しました。AnacondaのPATHはシステム環境変数で、読み込んでほしいlibstdc++-6.dllはユーザー環境変数に設定しているため、AnacondaのPATHはユーザー環境変数に設定し直しました。
いずれAnacondaのプログラムを動かしたときに問題が発生しそうですが、今のところAnacondaを使う予定はないのでとりあえずこれで解決したことにします。

参考資料

MinGWのg++でコンパイルしたstd::coutを含むプログラムが強制終了する問題について
what is libstdc++.so file
The GNU C++ Library
Locate a DLL
DLL 検索順序 (1)
DLL のロードの順序 教えて!goo(WebArchive)
Windowsでファイル検索(TECH+)
WindowsでAnacondaのPATHを通そう

  1. Linuxではldd(「list dynamic dependencies」の略)が使われる。WindowsでもGit BashやMSYS2において使うことができる。Windowsで依存関係を調べる方法はDependency WalkerDependenciesdumpbinが有名。

  2. DLLが検索できなかった場合、システムエラーが発生してそもそも実行できません。今回の状況が発生するのは、同じ名前で想定していないDLLを誤って読み込んでしまっているためです。

0
0
0

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
0
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?