mremap の作業を再現して、mmap されたメモリ/ファイルを拡張しようとしています。私は大まかにこの例に従いましたが、匿名マップを対象としていますが、名前付きファイルにしたいのです (これはプログラミング言語インタープリターであるため、このファイルはインタープリター状態の「コア ダンプ」に相当します)。
#ifブロックの入れ子で原文が読みにくい。したがって、これは「抽出」されたものですが、実際のコードです (デバッグ中のコンパイル パス用)。完全なソースはここで表示できますが、問題のコードは含まれていません。コミットされておらず、機能していないためです。:) ただし、mremap バージョンと malloc フォールバックがあります。
unsigned pgsz /*= getpagesize()*/ = 4096;
typedef struct {
int fd;
unsigned char *base;
unsigned used;
unsigned max;
} mfile;
/* reallocate and possibly move mem->base */
mfile *growmem(mfile *mem,
unsigned sz)
{
void *tmp;
int newfd;
printf("growmem: %p %u + %u\n", mem->base, mem->max, sz);
if (sz < pgsz) sz = pgsz;
else sz = (sz/pgsz + 1) * pgsz;
sz += mem->max;
printf("growmem: new size: %u\n", sz);
msync(mem->base, mem->used, MS_SYNC);
newfd = dup(mem->fd);
tmp = mmap(NULL, sz,
PROT_READ|PROT_WRITE,
MAP_SHARED | (mem->fd == -1? MAP_ANONYMOUS : 0),
newfd, 0);
if (tmp == MAP_FAILED)
error(VMerror, "unable to grow memory");
memcpy(tmp, mem->base, mem->used);
munmap(mem->base, mem->max);
mem->fd = newfd;
mem->base = tmp;
mem->max = sz;
return mem;
}
これは呼び出されたときに機能するように見えますが、後でプログラムがクラッシュします。正確な場所は突き止めていませんが、メインの eval ループをトレースすると、メモリの新しい部分に書き込みアクセスできないように見えます。失敗した演算子は、新しいディクショナリ オブジェクトを割り当てます。そして、同じファイル記述子を再利用して何かばかげたことをしたのではないかと思います。編集: 新しいファイル記述子、同じ segfault。
Breakpoint 2, eval (ctx=0x80049a70) at src/bin/itp.c:482
482 object t = top(ctx->lo, ctx->es, 0);
(gdb)
Continuing.
evalload <name "dict">
eval
Executing: <operator 24>
Stack: 0:<integer 1>1:<integer 0>2:<integer 0>3:<integer 1>4:<integer 0>5:<integer 0>6:<array L 229 100 78 0>7:<integer 1>8:<dict L 102 16 658 0>9:<integer 8>
Dict Stack: 0:<dict G 358 10 10 0>1:<dict G 358 100 188 0>2:<dict L 102 100 9 0>3:<dict G 486 24 310 0>4:<dict L 102 6 80 0>
Exec Stack: 0:<operator 60>1:<array G 357 2 387 6>2:<boolean false>3:<array G 325 17 416 14>4:<operator 54>5:<operator 63>6:<array G 453 18 414 0>7:<array G 325 1 414 17>8:<array G 325 4 413 5>9:<boolean false>10:<file>11:<file>12:<array L 101 3 103 16>13:<array L 101 1 113 4>14:<operator 24>
2929 [main] itp 613952 exception::handle: Exception: STATUS_ACCESS_VIOLATION
10097 [main] itp 613952 open_stackdumpfile: Dumping stack trace to itp.exe.stackdump
Program received signal SIGSEGV, Segmentation fault.
0x61129ab9 in memset () from /usr/bin/cygwin1.dll
(gdb)
Continuing.
warning: SuspendThread failed. (winerr 6)
[Inferior 1 (process 613952) exited with code 0105400]
(gdb)
正確なラインを追跡しました。新しいメモリの一部にアクセスしようとすると、後で割り当てに失敗します。
unsigned mfalloc(mfile *mem,
unsigned sz)
{
unsigned adr = mem->used;
if (sz) {
if (sz + mem->used >= mem->max)
mem = growmem(mem,sz);
mem->used += sz;
memset(mem->base+adr, 0, sz); //bzero(mem->base+adr, sz);
/* bus error with mremap(SHARED,ANON)! */
}
return adr;
}
私は何を間違っていますか?
PS。エラー呼び出しの直前にデバッガーを一時停止しました。変数値のいずれかが役立つ場合は、それらを取得できます。はmem->fd
12 であるため、このコードが以前に遭遇したのとまったく同じ SHARED/ANON エラーには遭遇していませんが、この組み合わせを避けるために mmap 呼び出しでいくつかの調整を行う必要があります。
編集:メモリ/ファイルの古い内容に問題なくアクセスしているようです。使えない新しいスペースです。既存の開いているファイルがあると、より大きな連続したマップが妨げられますか? うーん。おそらく、msync、munmap、fdclose、再オープン、mmap の順に実行する必要があります。... mfile 構造体はファイル名を保存する必要があるため、テストするには再設計が必要になります。...