51562


rubyのloadとrequireの違いは、ドキュメントでは以下のように説明されています。

> Kernel.#require は同じファイルは一度だけしかロードしませんが、 Kernel.#load は無条件にロードします。  
>  また、require は拡張子.rb や .so を自動的に補完しますが、 load は行いません。

しかし、以下のプログラムではloadもrequireも正しく動作するにもかかわらず、

[code]

    #! ruby253 -EWindows-31J
    # -*- mode:ruby; coding:Windows-31J -*-
    $:.push("c:/test/test")
    load "sub.rb"
    require "sub.rb"
    
[/code]

以下のプログラムではrequireのみが失敗します。loadは成功します。

[code]

    #! ruby253 -EWindows-31J
    # -*- mode:ruby; coding:Windows-31J -*-
    $:.push("c:/テスト/test")
    load "sub.rb"
    require "sub.rb"
    
[/code]

動作環境はWindows7 +
Ruby2.5.3です。この挙動はrubyの仕様上正しいのか、二番目の例でrequireを成功させるにはどのように記述すべきなのか、教えていただけるとたいへん助かります。よろしくお願いします。


CC BY-SA 4.0
2018-12-27T03:10:31.900
51543
2018-12-27T11:13:13.957
31398
question
ruby
load と requireの違い


Ruby自体の不具合と思われます。関係がありそうなIssueとして下記がありますが、未解決です。

[Bug #9737: Non-ASCII characters in the path to ruby executable break require
paths - Ruby trunk - Ruby Issue Tracking System](https://bugs.ruby-
lang.org/issues/9737)

ライブラリのファイルへの絶対パス(ルートからの各ディレクトリ名及びファイル名)にASCII以外の文字が含まれていない場合は、何らかの不具合が他にも発生する可能性が高いです。これらを回避したい場合は、
**ASCII文字のみのディレクトリ名およびファイル名を使用してください。**

どうしても日本語のディレクトリ名を使いたいというのであれば、RubyのIssueへ問題を報告し、修正して貰う、または、自分でパッチを作って送りつけるしかないでしょう。

* * *

以下、私が手元で調べた詳細です。

手元のWin 10, ruby 2.5.3p105 [x64-mingw32] (Ruby
Instller)で確認する限り、`load`でも`require`でも"stack level too deep
(SystemStackError)"が発生しました。また、読み込みすらしていない次のコードでもSystemStackErrorが発生しました。

[code]

    # coding: Windows-31J
    $:.push("テスト")
    puts $:
    
[/code]

ソースファイルをUTF-8にした場合は正常に動作し、`require`や`load`も問題なく動作しました。また、WSLのUbuntu環境(UTF-8)でRuby
2.5.3および2.6.0で試したところ、`pust $:`は問題ないですが、`require`や`load`を用いた場合は次のような結果になりました。

  * ソースファイルがUTF-8の場合はSystemStackErrorで落ちます。
  * ソースファイルがWindows-31Jの場合はSystemStackErrorで落ちませんが、ディレクトリを辿れずライブラリファイルを見つけられません。

となりました。

ソースコードを見ると`$:`自体は`rb_ary_new()`で作成された普通のArrayであり、`vm->load_path`としてC上では存在します。しかし、詳しくはソースを追っていませんが、何かのタイミングでパスを展開し、キャッシュを持つようになっているようです。そこら辺の処理でASCII以外の文字の処理が再帰してSystemStackErrorになっていると思われます。

OS、Rubyのバージョン、環境、パスの書き方によって異なる結果になると思われますので、質問者さんが出くわした現象では無いかも知れません。いずれにしても、ASCII以外は使わないことぐらいしか、確実な回避策は無いと思います。


CC BY-SA 4.0
2018-12-27T11:13:13.957
51562
2018-12-27T11:13:13.957
7347
51543
answer