まず lua table のソースコードの長さ取得部分(ltable.c)を見てみましょう

j は配列部分の長さです。まず配列の長さが 0 より大きく、かつ配列の最後の要素が nil の場合、二分探索で長さを探して返します。

t->node が table の hash 部分の格納場所です。もし空であれば、配列の長さを返します。

最初の例:

この場合、配列の長さが初期化されていて、t の長さは 7 です。なぜでしょうか。最後の要素が nil ではないからです。

以下の場合、t の長さは 5 です。

2番目の例:

誰でも t の長さが 5 であることは分かるでしょう。

この場合、t の長さはいくつでしょうか???

答えは 2 です。なぜでしょうか?

t

t

次に(lvm.c)に入ります

次に(ltable.c)の luaH_newkey 関数を呼び出します

そして rehash を呼び出します

この部分は実際には配列部分と hash 部分に格納する計算です。nums は数値の分布を統計しています。コードをよく見ると、配列の長さは 2 の n 乗であることが分かります。

ここで nil は数値ではないため統計に含まれません。よって 1、2、5、6 から配列の長さは 4 と計算され、残りの部分は node 部分に格納されます。

table は配列と node hash 部分から構成されています。

このように、先ほど見た関数によると、4番目が nil なので、二分探索で求められる長さは 2 です。

これが lua 配列内に nil がある場合に起こり得る落とし穴です。もちろん rehash が原因です。

原文アドレス:https://www.cnblogs.com/wallini/p/4188499.html