0

私は、教授が変更できない変数とプロトタイプ宣言を含むコードを提供してくれたプロジェクトを行っています。1つは構造体であり、その構造体へのポインタは次のようにtypedefされpStudentRecordます。

typedef struct
{
  char* firstName;
  char* lastName;
  int id;
  float mark;
}* pStudentRecord;

と呼ばれるこのタイプへのポインタを使用しますg_ppRecords。これは、上記の構造体へのポインターの動的配列になります。

ここで私の質問が出てきます。レコードはファイルから読み取られます。指定されたファイル名が存在しない場合は、新しいファイル名が作成されます。g_ppRecordsユーザーが最初の新しいレコードを追加するたびに、ポインターを初期化しています。

if(!n) //where n = number of records
  g_ppRecords = (pStudentRecord*)  malloc(sizeof(pStudentRecord));

g_ppRecords[n] = (pStudentRecord) malloc(16);

このコードは、これまで実行するたびに機能しますが、方法がわかりません。さらにレコードを追加するpStudentRecordと、の次の位置に新しいポインタ()が作成されg_ppRecordsます。私の理解では、その新しいポインタ用のスペースを割り当てていませんが、問題が発生することなく動作するたびに。新しい構造体のメンバーに正常にアクセスでき、ヒープ破損エラーやアクセス違反などは発生しません。私の懸念は正しいですか、それとも私は自分自身を疑っていますか?

4

3 に答える 3

3

あなたが示したコードに基づいて、あなたの懸念は有効です。

この行:

g_ppRecords = (pStudentRecord*)  malloc(sizeof(pStudentRecord));

単一 のに十分なスペースのみを割り当てpStudentRecordます。pStudentRecordこれを、で単一の要素のみを持つの配列と考えてくださいg_ppRecords[0]

さらにレコードを追加すると、新しいポインタ(pStudentRecord)がの次の位置に作成されg_ppRecordsます。

ここで問題となるのは、ここで説明したことを実行したときに何が起こるかということです。新しいポインタを追加するとどうなりますか?reallocのためにより多くのスペースを取得するために使用しない限り、レコードへのより多くのポインターのためにその配列にスペースg_ppRecordsありません。malloc2番目の要素に新しいポインタがある場合、つまり:

g_ppRecords[1] = (pStudentRecord) malloc(16);

次に、割り当てていないメモリを使用しg_ppRecords[1]ています。これは機能しているように見えるかもしれませんが、このメモリはあなたのものではありません。新しいポインタを追加し続けると、最終的にプログラムが壊れます。または、コードの別の部分にまったく関係のない何かが原因でプログラムが破損する可能性があります。

修正は、最初に配列を割り当てて、 1つだけではなく、複数のポインターを保持できるようにする必要があることです。malloc最初の行でこれをどのように行うことができますか?

structを使用するためにメモリを割り当てるときはmalloc(16)、作成してはならないデータ構造について、具体的にstructは常に16バイトを占めるという仮定を立てていることを付け加えておきます。:を匿名typedefからのポインタに直接指定すると、それをより一般的なものにstruct変更できますが16、これは質問に直接関係するものではなく、教授に尋ねる必要があります。

于 2012-09-12T14:51:52.320 に答える
1

原則としてmalloc( sizeof( type ))、特に型キャストによって型が難読化されている場合は、避けるようにしてください。変数でsizeofを呼び出す方がはるかに安全ですmalloc( sizeof x )。また、Cでは、mallocからのリターンをキャストしないでください。つまり、1つのレコードにのみスペースを割り当てる代わりに、次のようにします。

g_ppRecords = (pStudentRecord*)  malloc(sizeof(pStudentRecord));

次のように記述して、n個のレコードにスペースを割り当てることをお勧めします。

g_ppRecords = malloc( n * sizeof *g_ppRecords );
于 2012-09-12T18:09:02.830 に答える
0
typedef struct
{
  char* firstName;
  char* lastName;
  int id;
  float mark;
}* pStudentRecord;

これは無名構造体です。ここで少し変ですが、何かを教えてくれるかもしれません。これを実行して、新しいものを作成します。

pStudentRecord ptr;
ptr = malloc(sizeof(*ptr));

これにより、適切な量のメモリが自動的に malloc されます。

ポインターを保持するために配列を malloc する必要があるため、まだ問題があります。そのためには、次のようにします。

pStudentRecord* g_ppRecords = malloc(n * sizeof(pStudentRecord));

その後、次のように g_ppRecords を使用できます。

pStudentRecord ptr = g_ppRecords[3];

すべてをまとめると、カスタム アロケーターができます。

pStudentRecord* g_ppRecords = malloc(n * sizeof(pStudentRecord));

for (size_t i = 0; i < n; ++i)
{
  pStudentRecord ptr;
  g_ppRecords[i] = malloc(sizeof(*ptr));
}

私はコンパイルとテストをせずにこれをすべて書いたので、エラーがあるかもしれません (しかし、それは私の宿題ではありません :-) )

于 2012-09-12T16:45:30.827 に答える