はじめに
こんにちは、こふです。
AtCoder のコンテスト中に gcc/g++
の環境が死んでいるかもしれなくて詰みました。
検証した順に上からまとめていますが、結論としてはデバッグしていた時に書いていた特定の文法がまずかったようでした。
つまり、同じエラーで困っているあなたに伝えるとしたら文法のミスが絶対にないといえるかを何度も確認してほしいと思います。ミスでなくても、推奨されない書き方があるかも知れません。
void dfs(vector<pii> p, int s, vector<bool> &visited) {
int n = (int)p.size();
visited.at(s) = true;
rep(i, 6) {
rep(j, n) {
if (j == s)
continue;
if (visited.at(j))
continue;
int next_x = p.at(s).first + dx[i];
int next_y = p.at(s).second + dy[i];
// ここがダメ??
cout << p.at(s).first << " " << p.at(s).second << endl;
if (p.at(j) == make_pair(next_x, next_y)) {
dfs(p, j, visited);
}
}
}
return;
}
ちなみに僕の文法ミス?は、cout
の出力に関して、型が複数入った複雑なものであったこともまずかったかもしれません。複数入れたときに、int 型
、string 型
の混在も良くないかと思い、文字列で統一するとエラーは起きませんでした。
ですが、今までも書いてたはずでした。しかし、vector
の中の pair
を取り出して、出力というパターンはすべてのファイルで全文検索かけても出てこなかったので、実は初めて書いてしまったようです。これは今後使わないよう気をつけます。
ここからは文法ミス?に気づくまで手探りで再インストールなどをした記録です。
コンテスト中にどの文法が悪いのか手探りで確認してもダメでした。というか、今までと変わって違う書き方をしたわけでもないつもりだったからです。
その後に Docker
を使った Debian
環境では同じコードで動いたので、完全にローカルの環境が死んでいたのか?と思いましたが、萎えてコンテストはやめました。
翌日解くと C 含め D 問題まで全然解けるやつでした、残念。今後絶対起こってほしくないので、調査して直す必要があります。
具体的なエラー
このようなエラーが出ていました。
g++ c.cpp
A linker snapshot was created at:
ld: Assertion failed: (_file->_atomsArrayCount == computedAtomCount && "more atoms allocated than expected"), function parse, file macho_relocatable_file.cpp, line 2061.
collect2: error: ld returned 1 exit status
なにかリンカのエラーのようです。
原因調査
which g++
すると
❯ which -a -s g++
/usr/local/bin/g++ -> /opt/homebrew/Cellar/gcc/12.2.0/bin/g++-12
/usr/local/bin/g++ -> /opt/homebrew/Cellar/gcc/12.2.0/bin/g++-12
/usr/bin/g++
シンボリックリンクを貼っているので 1 つしか出ないはずが、なぜか 3 箇所に出ています。これが原因かは現状わかりません。
ここで、数日前に Xcode の謎の追加パッケージのエラーが出たことを思い出します。インストールしてもインストールしても再インストールを要求されていました。
そのときに何らかのインストールが走っていましたが、Apple の MacOS のアップデートがあることに気づき、ダウンロードを始めます。これで Xcode 側でのインストール要求は止まりました。
そして再起動をしていました。このときにインストールが未完了で終わってしまい、環境を壊してしまったかな?と思い、まずはここを直してみます。
直す
一度、homebrew でインストールしている gcc を再インストールしてみます。そもそも、なぜ gcc をインストールするかというと、標準でインストールされているのは clang だったはずだからです。
確かに、gcc をアンインストールすると、#include <bits/stdc++.h>
がインクルードできなくなりました。つまり、削除は出来ています。
brew uninstall gcc
brew install gcc
そして、シンボリックリンクを貼り直します。ちなみに、前までg++-11
だったような。
❯ sudo unlink /usr/local/bin/g++
❯ sudo ln -s /opt/homebrew/bin/g++-12 /usr/local/bin/g++
これでコンパイル出来なかったのが、できるか?
・・・
と思っていたら、まだダメでした。
再度直す
XCode とセットでインストールした何か(CommandLineTools
)が壊れている可能性もあるため、削除して再インストールしてみます。
❯ sudo rm -rf /Library/Developer/CommandLineTools
❯ xcode-select --install
❯ g++ -Wall d.cpp
d.cpp:1:10: fatal error: 'bits/stdc++.h' file not found
#include <bits/stdc++.h>
^~~~~~~~~~~~~~~
1 error generated.
g++でなく clang が動いています。
gcc の絶対パスを指定してコンパイルしましたが、やはりダメでした。
❯ /opt/homebrew/bin/g++-12 c.cpp
ld: Assertion failed: (_file->_atomsArrayCount == computedAtomCount && "more atoms allocated than expected"), function parse, file macho_relocatable_file.cpp, line 2061.
collect2: error: ld returned 1 exit status
この記事、リンクエラーの話 - Qiitaに関連するエラー文が出てきますが、コマンド、ファイルの指定は間違えていないので、関連はないはずです。
でも、なにかリンカのエラーも何らかの相性が悪くて、という可能性も捨てきれません。
ここで、次の選択肢を迫られます。
- gcc/g++を使う
- clang に移行する
途中で特定のデバッグのコードcout<< vector.at(0).first << " " << vector.at(0).second << endl
のようなコードを消すとg++
で通りました。これが悪さしているはずはないと思っていたのに、悪さしていたようです。
出力の順として、int型の変数 空文字列 int型の変数
としていた箇所がなぜ??
ただ、このような普通の特殊でないコードでエラーが出るなら競プロに支障が出ます。
ここで、cout<< to_string(vector.at(0).first) << " " << to_string(vector.at(0).second) << endl
とするとコンパイル出来ました、なんで?
cout
のレファレンスを見てみますが、そういった注意事項はありませんでした。
clang でコンパイルするなら、include
をそれぞれ書いてあげる必要はでてきますね。でも、それでもコンパイルで着なかったので、文法のミスということになるでしょう。
しかし、Debian
やAtCoder
の環境でコンパイルできるのがやはり不自然です。ローカルの環境が壊れている可能性は捨てきれません・・・
おわりに
結局は自分の文法ミス?にも思えたので、自分を疑う姿勢が大事だとあらためて認識しました。
しかし、なぜ Debian で動いて Mac のローカルにインストールした gcc では動かないかはわかりませんでした。
もしこれが MacOS 起因の問題だとしたら Mac を使いたくなくなってしまうかも知れません。