4

クラス プロジェクトとして、ファイルのログ ベースのファイル システムの実装に取り​​組んでいます。私の 64 ビット OS X ラップトップではかなりの量のコードが動作していますが、CS 部門の 32 ビット Linux マシンでコードを実行しようとすると、セグ フォールトが発生します。

与えられた API では、一度に DISK_SECTOR_SIZE (512) バイトを書き込むことができます。私たちのログ レコードは、ユーザーが書き込みたい 512 バイトといくつかのメタデータ (書き込み先のセクター、操作の種類など) で構成されています。

全体として、「レコード」オブジェクトのサイズは 528 バイトです。これは、各ログ レコードがディスク上の 2 セクタにまたがることを意味します。

最初のレコードは、セクター 0 に 0 から 512 を書き込み、セクター 1 に 0 から 15 を書き込みます。2 番目のレコードは、セクター 1 に 16 から 512 を書き込み、セクター 2 に 0 から 31 を書き込みます。セクター 3 の 0-47。ETC。

したがって、変更する 2 つのセクタを 2 つの新たに割り当てられたバッファに読み込み、レコードから buf1+512 オフセット バイトの計算されたオフセットにコピーします。これは両方のマシンで正しく機能します。

ただし、2 番目の memcpy は失敗します。具体的には、以下のコードの「record+DISK_SECTOR_SIZE-offset」は segfaults ですが、Linux マシンでのみ発生します。いくつかのランダムなテストを実行すると、さらに興味深いものになります。Linux マシンは、sizeof(Record) が 528 であると報告します。したがって、record+500 から buf に 1 バイトの memcpy を実行しようとしても、問題はないはずです。

実際、レコードから取得できる最大のオフセットは 254 です。つまり、memcpy(buf1, record+254, 1) は機能しますが、memcpy(buf1, record+255, 1) は segfault になります。

誰かが私が欠けているものを知っていますか?

Record *record = malloc(sizeof(Record));
record->tid = tid;
record->opType = OP_WRITE;
record->opArg = sector;
int i;
for (i = 0; i < DISK_SECTOR_SIZE; i++) {
  record->data[i] = buf[i]; // *buf is passed into this function
}

char* buf1 = malloc(DISK_SECTOR_SIZE);
char* buf2 = malloc(DISK_SECTOR_SIZE);

d_read(ad->disk, ad->curLogSector, buf1);  // API to read a specified sector into a buffer
d_read(ad->disk, ad->curLogSector+1, buf2);

memcpy(buf1+offset, record, DISK_SECTOR_SIZE-offset);
memcpy(buf2, record+DISK_SECTOR_SIZE-offset, offset+sizeof(Record)-sizeof(record->data));
4

4 に答える 4

10

ポインタpに1を追加する場合、1バイトを追加するのではなく、sizeof(p)バイトを追加します。

したがって、この場合、追加する前ににキャストrecordする必要があります。char*現在、record+500実際には500 * 528=264,000バイト離れていrecordます。

もちろん、これはセグメンテーション違反が発生しない理由を説明するものでmemcpy(buf, record+254, 1)はありません。ただ「ラッキー」だと思います。

于 2010-04-08T18:07:40.550 に答える
3

record+BLAHつまり、マシンコードに変換するBLAH*sizeof(Record)と、のアドレスに追加されrecordます。

したがって、 ;record+500から500バイトではありません。recordから500*528=264000バイト離れていrecordます。

于 2010-04-08T18:05:36.527 に答える
2

Linuxコードをvalgrind-の下で実行してみてください。これにより、問題の根本的な原因に直接たどり着くことができます。

于 2010-04-08T18:05:00.660 に答える
0

record+DISK_SECTOR_SIZE-オフセットが問題です。record + 1は、record+1のアドレスを提供しません。

それはあなたとrecord+1 * sizeof(record)のアドレスを与えます。(ポインターをインクリメントまたはデクリメントすると、使用しているデータ型の倍数になります。次のようにレコードポインターを型キャストするだけです:(byte *)record + DISK_SECTOR_SIZE-offset。レコードは少なくともDISK_SECTOR_SIZEの長さであるため、セグメンテーションエラーを説明します。 。

于 2010-04-08T18:31:57.933 に答える