Project

General

Profile

Bug #13004

Updated by nobu (Nobuyoshi Nakada) over 7 years ago

 きしもとです 

 
 
  拡張ライブラリで `rb_get_kwargs` rb_get_kwargs を使おうとしたところ、いくつか変に 
 
  感じた点がありましたので、確認をお願いしたくこちらにメイルします。 
 
  もしバグでしたらチケットにまとめます。 

 
 
  (1) `values`を渡すと、全て変更(初期化)される。 

 valuesを渡すと、全て変更(初期化)される。 
 
  extension(.ja).rdoc には、 

 
 
  > ``` 
 >                          ...    If an optional key is not present in 
 
  >    +keyword_hash+, the corresponding element in +values+ is not changed. 
 
 
  > ``` 

 > ``` 
 >                                            ...省略可能キーワー 
 
  >    ドがない場合は,values中の対応する要素は変更されません. 
 > ``` 

 
 
  とあるが、コードでは、 

 ```C 
 
 
  1866       if (values) { 
 
  1867           for (j = 0; j < required + optional; j++) { 
 
  1868               values[j] = Qundef; 
 
  1869           } 
 
  1870       } 
 ``` 

 となっていて、`values`が非`NULL`であれば一律に `Qundef` 
 
  となっていて、valuesが非NULLであれば一律に Qundef で初期化している。 

 
 
  (2) "unknown keyword" `ArgumentError` ArgumentError`raise` raise しそこねることがある。 

 
 
  該当部分のコードはこうなっていて、 

 ```C 
 
 
  1898       if (!rest && keyword_hash) { 
 
  1899           if (RHASH_SIZE(keyword_hash) > (unsigned int)j) { 
 
  1900               unknown_keyword_error(keyword_hash, table, required+optional); 
 
  1901           } 
 
  1902       } 
 ``` 

 
 
  ここで `j` には認識されたキーワード引数の個数が入っていて、`values`が 
 `NULL`の時には`keyword_hash`の中身が変更されず、恐らくその意図通りの 
 動作になるが、`values`が非`NULL`の場合は`keyword_hash`からエントリが 
 j には認識されたキーワード引数の個数が入っていて、valuesが 
  NULLの時にはkeyword_hashの中身が変更されず、恐らくその意図通りの 
  動作になるが、valuesが非NULLの場合はkeyword_hashからエントリが 
  除かれるため、認識できなかった引数があってもこのチェックを通り 
 抜けてしまうことがある(`extract_kwarg`マクロも参照)。 

 ```C 
 
  抜けてしまうことがある(extract_kwargマクロも参照)。 
 
  1855 #define extract_kwarg(keyword, val) \ 
 
  1856       (key = (st_data_t)(keyword), values ? \ 
 
  1857        st_delete(rb_hash_tbl_raw(keyword_hash), &key, (val)) : \ 
 
  1858        st_lookup(rb_hash_tbl_raw(keyword_hash), key, (val))) 
 ``` 

 
 
  (3) 使用されない要素は`keyword_hash`に残されるだけで、別には保存されない。 

 使用されない要素はkeyword_hashに残されるだけで、別には保存されない。 
 
  extension(.ja).rdoc には、 

 
 
  > ``` 
 >    If +optional+ is negative, rest of +keyword_hash+ are stored in the 
 
  >    next to optional +values+ as a new Hash, ... 
 
 
  > ``` 

 > ``` 
 >    keyword_hashに使用されない要素がある場合は,optionalが負なら 
 
  >    新しいHashとして省略可能引数の次に保存されますが,... 
 > ``` 

 
 
  とあるが、該当するコードが見つからない。またもし、そのような動作を 
 
  するのであれば、ドキュメントのこの関数に関する記述の冒頭部に、 
 `values`のサイズは必ず「`required+optional 
  valuesのサイズは必ず「required+optional + 1`」以上でなければ 
 1」以上でなければ 
  ならないと書く必要があるように思う。 

Back