0

こんにちは、次のコードがあります

#include <stdio.h>
#include <conio.h>
typedef struct test
{
    int a;
    int b;
    int c[10];
}tester;

typedef struct done
{
    tester* t;
    int nn;
}doner;

void main()
{
    doner d;
    d.t = (tester*)malloc(sizeof(d.t));
    d.t->a = 10;
    d.t->c[0] = 10;
    printf("%d\n", d.t->a);
    getch();
    return;
}

私は声明を考えます:

d.t = (tester*)malloc(sizeof(d.t));

は正しくありません:

d.t = (tester*)malloc(sizeof(tester));

しかし、このコードを実行してもクラッシュしません。その理由を教えてください。

4

4 に答える 4

1

クラッシュしていないという事実は、未定義の動作があるためです。正しいコードは 2 番目のものですが、キャストする必要はありません。

d.t = malloc(sizeof(tester));

また、malloc されたポインターを解放する必要があります。

多くのシステムでは、malloc されたバッファへの書き込み時にヒープがチェックされず、割り当てられたメモリを解放するときにのみチェックされます。このような場合、メモリを解放するときに何らかのクラッシュが発生する可能性があります。

于 2012-07-18T09:53:05.333 に答える
1

クラッシュしないという事実は、この種のメモリ割り当てのバグが非常に潜行性が高く、検出が難しい大きな理由です。プログラムは 1 つの構造体のみを割り当て、それをいっぱいにすることはありません。そのため、割り当てられたメモリ量を超えて実行されても、他には何にも影響しません。

mallocプログラムが動的に割り当てられたメモリをより多く使用した場合、構造がヒープのリンク メタデータを上書きしたために/の呼び出しがfreeクラッシュを引き起こすか、独自の malloc されたデータに書き込むプログラムの他の部分が構造を上書きします。いずれにせよ、きれいではありません。

于 2012-07-18T09:54:59.913 に答える
0

はい、あなたが正しい。は単なるポインターsizeof(tester)であるため、 である必要があります。d.t

ここで、クラッシュの保証ではないUndefined Behaviorsizeof(d.t)を呼び出すと記述します。プログラムが正しく実行されたり、正しく実行されなかったり、クラッシュしたり、ピザを注文したりする可能性があります。未定義の動作を持つプログラムで何が起こるかについての保証はありません。それを引き起こす構造の前であってもです。

freeed メモリの ingとしてmalloc- この小さなサンプル プログラムでは、システムがプログラムの終了後にメモリを解放するため、心配する必要はありませんが、一般的には、割り当てたものは何でも解放して回避するようにしてください。大規模なプログラムではメモリ リークが発生します。

于 2012-07-18T09:53:28.657 に答える
0

デフォルトでは、リンカは起動時にプログラムに 1MiB の (スタック) メモリを割り当てるよう OS に要求します。すべての参照が、プログラム用に OS によって予約された同じメモリ (同じアドレス空間) にあるため、プログラムはクラッシュしません。技術的には、そのメモリを割り当てていませんが、ポインタがまだ有効なメモリ範囲内にあるため、プログラムはそれにアクセスできます。これは、ほとんどの場合、dt->c[10] に書き込むことができるのと同じです (ただし、有効なインデックスは 0 ~ 9 です)。割り当てられたメモリ外のメモリ位置に対応するポインタが使用されると、クラッシュが発生します。興味がある場合は、詳細な理解のためにGoogle Page Faultを参照してください。

于 2012-07-18T10:48:07.670 に答える