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

## std::coutを使うと落ちる
2年前くらいから、Mingw-w64のg++でコンパイルしたプログラムが実行できない（数秒フリーズ後何も出力せず終了）することに気が付きました。
例えば、以下に示すようなプログラムが動きませんでした。
```C++:test.cpp
#include <iostream>
int main() {
  int a = 10;
  std::cout << a << std::endl;
  return 0;
}
```
これを`g++ test.cpp`でコンパイルした実行可能ファイルが落ちます。
色々試してみると、printfを使ったプログラムなら問題なく動作することが分かりました。
```C++
#include <iostream>
int main() {
  int a = 10;
  printf("%d\n", a);
  return 0;
}
```
これに気づいた当初は焦りましたが、そこまでWindowsでg++を使わなかったので大きな問題にはならず、~~調査も面倒だったので~~何かの拍子に直ることを期待して~~放置~~対応を後回しにしていましたが、重い腰を上げて直すことにしました。

## 静的リンクを試す
この問題について調べていると、[12年前に似たような問題が発生した記事](https://ykicisk.hatenablog.com/entry/2013/12/12/192252)を発見したので、この記事の流れに沿って進めていきました。
まず、g++自体がおかしいのか確認するため、静的リンクでコンパイルしてみました。`g++ test.cpp -static`で共有ライブラリとのリンクを抑止してビルドを行うと、正しく標準出力されたのでg++自体がおかしいわけではなさそうです。
ところで、実行可能ファイルがどの共有ライブラリ（DLL）に依存しているかは[`dumpbin`](https://learn.microsoft.com/ja-jp/cpp/build/reference/dependents)コマンドで調べることができます[^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読み込みがうまく行っていないことが分かりました。

[^1]: Linuxでは[`ldd`（「list dynamic dependencies」の略）](https://wa3.i-3-i.info/word13813.html)が使われる。WindowsでもGit Bashや[MSYS2](https://qiita.com/koyukitukimino/items/df76f7fdb8512920d75b)において[使うことができる](https://siuncyclone.hatenablog.com/entry/2018/07/21/194629)。Windowsで依存関係を調べる方法は[Dependency Walker](http://yohshiy.blog.fc2.com/blog-entry-65.html)や[Dependencies](https://hourouneko.hateblo.jp/entry/2022/10/12/113642)、[dumpbin](https://amachang.hatenablog.com/entry/20090713/1247455262)が有名。

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

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

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

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

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

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

Anacondaはかなり前からインストールしていたものの、[PATHを通した](https://golabo.net/windows-path-anaconda/)のは後からだったので気づかず、今回の問題が発生していたということでしょう。

## 対処法
* Anadondaを削除する
* AnacondaのPATHを変える

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

## 参考資料
[MinGWのg++でコンパイルしたstd::coutを含むプログラムが強制終了する問題について](https://ykicisk.hatenablog.com/entry/2013/12/12/192252)
[what is libstdc++.so file](https://www.linuxquestions.org/questions/linux-newbie-8/what-is-libstdc-so-file-604929/)
[The GNU C++ Library](https://gcc.gnu.org/onlinedocs/libstdc++/)
[Locate a DLL](https://www.ibm.com/docs/ja/informix-servers/15.0.0?topic=environments-locate-dll)
[DLL 検索順序 (1)](https://nyaruru.hatenablog.com/entry/20040930/p2)
[DLL のロードの順序 教えて!goo（WebArchive）](http://web.archive.org/web/20160821085838/http://oshiete.goo.ne.jp/qa/1099463.html)
[Windowsでファイル検索（TECH+）](https://news.mynavi.jp/techplus/article/natonakucommand-27/)
[WindowsでAnacondaのPATHを通そう](https://golabo.net/windows-path-anaconda/)