1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

またしてもFiddleの利用中にGCにメモリ領域を回収されてまった話

Last updated at Posted at 2021-01-12

Fiddleの構造体のメンバーを何回も呼び出すと値が変わってしまうことがあります。
意気揚々としてisssue報告をしたのでしたが…

下、1000回呼び出すとだいたい値が変化する…

require 'fiddle/import'

module A
  extend Fiddle::Importer
  S = struct [
    'int8_t* hoge',
    'int8_t* fuga']
end

s = A::S.malloc
s.hoge = [*1..10].pack('c*')
s.fuga = [*1..10].reverse.pack('c*')

a1 = s.fuga[0,10].unpack('c*')

1000.times do
  s.fuga[0,10].unpack('c*')
end

b1 = s.fuga[0,10].unpack('c*')

if a1 == b1
  puts "OK"
else
  p a1, b1
end

ところが、これはバグではなく、文字列がGCによって回収されてしまうのだそうです。
以前にもFiddle::Closure::BlockCallerがGC回収されてしまう記事を書きましたが、これも全く同じパターンでして、

s.hoge = [*1..10].pack('c*')
s.fuga = [*1..10].reverse.pack('c*')

この = の右側の文字列は、何の変数にも代入されていないので、無慈悲にもGCに回収されてしまうのです。
回避策としては

s.hoge = memo1 = [*1..10].pack('c*')
s.fuga = memo2 = [*1..10].reverse.pack('c*')

のように変数に入れておくというのがあります。

FFIを利用してプログラミングを行う際には、よほどGCに注意しなければならないということを再確認しました。

この記事は以上です。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?