Ruby on Rails5にBootstrap4を導入しようとしたらstack smashing detectedエラー


# 目的
Apple M1チップ搭載のMac上のDocker環境でRails5を動かしています。ベースのイメージは`ruby:2.7.3`です。（ちなみに`ruby:2.5.8`でも同様の現象が生じました。）Rails自体は問題なくインストール、pumaでの起動ができるのですが、問題はBootstrapの導入を試みたときです。世の指南書にあるようにGemでBootstrapをインストールし、サーバを再起動して、適切に`application.scss`を記述して、いざブラウザ越しにアプリケーションへアクセスすると無残にも「このサイトにアクセスできません」状態となります。

サーバ側のログを確認すると

```
*** stack smashing detected ***: <unknown> terminated
```

とのこと。この`stack smashing detected`エラーをGoogleで検索してみると、C言語でスタックオーバーラン等が起こった時に出るエラーという解説がたくさん出てきます。**Gem使っていてC言語のエラーに遭遇するとか想定外**です。

このエラーに対する根本的な解決策を見出すのは困難であると考え、また、楽したいために導入したBootstrapで、そんな苦難の道を進むことになるのは本末転倒ですので、早々にGemを諦めて、もっと気軽にBootstrapを導入する方法を探りました。

というわけで、この文章の対象者は、

- RailsにBootstrapを導入したら`stack smashing detected`エラーに遭遇したが、
- そのエラーの根本解決を望んでいるわけではなく、
- Bootstrapが気軽に導入できればよい、

という状況の方になります。

# 環境
筆者の環境は以下です。
- Apple M1 Mac
- macOS Big Sur
- Docker Desktop 3.6.0
- イメージ ruby:2.7.3
- Rails 5.2.0
- Bootstrap 4.5.0

おそらくRubyの2系、Rails5（6は不明）、Bootstrap4または5を使用して`stack smashing detected`エラーが出るなら同じ状況かと思います。これらのバージョンより、M1のDockerというのが問題なのではないかという気がしています。

# とにかく素のBootstrapが入ればいい人向け
この場合は簡単です。（たぶんそういう人はQiita読んでいないと思いますが。）レイアウト等でCDNから`bootstrap.css`を引っ張ってくれば良いだけです。具体的には、`app/views/layouts/application.html.erb`に

```html
<!DOCTYPE html>
<html>
  <head>
    <title>Your App</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-\
track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reloa\
d' %>
  </head>

  <body>
    ...
  </body>
</html>
```
のような感じで、[Bootstrapの公式サイト](https://getbootstrap.jp/docs/4.5/getting-started/introduction/)の導入部分に示されているように、linkタグを埋め込んでしまえば普通に使えます。バージョンはお好きなものを。

CDNからの読み込みを避けたいという人も特に難しくはありません。その場合は上記公式サイトのダウンロードボタンをクリックし、`bootstrap.css`をダウンロードしてアプリケーションの`app/assets/stylesheets`ディレクトリに放り込みます。あとは`application.css`に

```
*= require_tree .
```
の記述があれば勝手にアセットパイプラインが働いて、いい感じに処理してくれます。

# SCSS使いたい人向け
おそらく本当に困っているのはこちらの人ではないでしょうか。筆者もそうなのですが、Bootstapが入ればいいとはいえ、やっぱり`primary`とか`secondary`の色は変えたい、とかそういう人です。素のCSSを置換して回るのはお手軽ではありません。

この場合には`bootstrap.scss`を導入する必要があります。上記のBootstrapの公式サイトのダウンロードページから、CSSファイルではなく**ソースファイルのダウンロード**をしてください。ダウンロードされたZipを解凍すると、その中に`scss`というディレクトリがあります。その中身を全てアプリケーションの`app/assets/stylesheets`の中に放り込みます。`bootstrap.scss`、`bootstrap-reboot.scss`、`bootstrap-grid.scss`や`_`から始まる複数のscssファイル、`vendor`、`utilities`、`mixins`の各ディレクトリも全てです。（結構なファイル数です。）

そして、`application.css`の拡張子を`application.scss`とSCSSに変更します。さらにそのファイルを開いて、

```
*= require_tree .
```
この行は削除してください。これを削除しないと、Railsのアセットパイプラインが、先程コピーした全ファイルを勝手な順序でコンパイルし始めてエラーが起こりまくります。

あとは手動でSCSSの文法を用いて、先程コピーした`bootstrap.scss`のみをインポートします。

```scss
/*                                                                            
 * This is a manifest file that'll be compiled into application.css, which will include all the files                                                      
 * listed below.                                                              
 *                                                                            
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's                                                                    
 * vendor/assets/stylesheets directory can be referenced here using a relative path.                                                                       
 *                                                                            
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the                                                         
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS                                                      
 * files in this directory. Styles in this file should be added after the last require_* statement.                                                        
 * It is generally better to create a new file per style scope.               
 *                                                                            
 *= require_self                                                              
 */

$theme-colors: (
  primary: #000000,
  secondary: #ffffff
);

@import "bootstrap";
```
`bootstrap.scss`の中身を見るとわかるのですが、他のSCSSファイルはその中でインポートされます。というか、この`bootstrap.scss`自体は他のファイルのインポートしかしていません。ちなみに上記コードの`@import`行の前にある`$theme-colors`変数の定義は不要です。これはBootstrapのプライマリカラーとセカンダリカラーを変更するためのものです。筆者はこのたったの4行の定義をBootstrapに反映したいために、`stack smashing detected`にぶち当たって苦労しました。

# まとめ
RailsにBootstrapを導入した時に起こる`stack smashing detected`エラーの回避方法を紹介しました。解決方法ではないことに注意してください。おそらく根本的なエラーの解決策を探るならば、Bootstrapを使わないで自力でCSSを書くほうがお手軽なのではないかと思います。エラーの出る理由くらい知りたい気はしますが、Dockerのバージョンアップ等を重ねるうちにいつの間にか解消されていることを期待します。