大域変数からの参照 - GC

大域変数から参照されているものは回収されてはならない。
まだ参照されているか?は、bss領域とかデータ領域の開始位置と終了位置の間を走査してやればよい。


開始や終了の位置はリンク時に解決されるので、ld のデフォルトリンカスクリプトを見ればわかりそう。


ld を --verbose で実行するとデフォルトのリンカスクリプトが表示されます。

ld --verbose
/home/taro/scheme/gc $ ld --verbose
GNU ld version 2.17 Debian GNU/Linux
  Supported emulations:
   elf_i386
   i386linux
   elf_x86_64
using internal linker script:
==================================================
/* Script for -z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
      "elf32-i386")

うんうん分かった。

extern "C" char  __bss_start[];
extern "C" char  _edata[];
extern "C" char  _end[];

このあたりだね。
cygwin やら COFF のクロスコンパイラだとここが違うんだろうけど、今は手元の Linux 環境で動作すれば良い。


リンカスクリプトを見て実験した感じだと __bss_start == _edata < _end が成り立つ。
アドレス範囲さえ分かれば、mark & sweep のコードは使いまわせるので大域変数での回収もこれにて完了。