2

私はメモリ割り当てについてもっと学ぼうとしているので、必要なサイズよりも小さいサイズのメモリを割り当てようとするとどうなるかを確認するために、以下のテスト コードを書きました。

#include <stdlib.h>
#include <stdio.h>

typedef struct {
    char *message;
    int number;
} Object;

int main(int argc, char *argv[]) {
    Object *obj = malloc(sizeof(Object) - 8);   
    printf("The size of the struct is: %ld\n", sizeof(Object));
    printf("The size of what was allocated is: %ld\n", sizeof(*obj));

    obj->message = "Hello there! My name is Chris!";
    obj->number = 435543;

    puts(obj->message);
    printf("%d\n", obj->number);

    free(obj);

    return 0;
}

まず、 sizeof(*obj) は、この場合に実際に割り当てられたメモリの量を確認する正しい方法ですか? 次に、十分なスペースを割り当てていないのに、構造体オブジェクトに値を代入できるのはなぜですか?

私のOSはUbuntu 12.10 64bitで、コンパイラはgcc 4.7.2です

valgrind の出力は次のとおりです。

==14257== Memcheck, a memory error detector
==14257== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==14257== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==14257== Command: ./ex
==14257== 
The size of the struct is: 16
The size of what was allocated is: 16
==14257== Invalid write of size 4
==14257==    at 0x400640: main (ex.c:15)
==14257==  Address 0x51f1048 is 0 bytes after a block of size 8 alloc'd
==14257==    at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14257==    by 0x400604: main (ex.c:10)
==14257== 
Hello there! My name is Chris!
==14257== Invalid read of size 4
==14257==    at 0x40065A: main (ex.c:18)
==14257==  Address 0x51f1048 is 0 bytes after a block of size 8 alloc'd
==14257==    at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14257==    by 0x400604: main (ex.c:10)
==14257== 
435543
==14257== 
==14257== HEAP SUMMARY:
==14257==     in use at exit: 0 bytes in 0 blocks
==14257==   total heap usage: 1 allocs, 1 frees, 8 bytes allocated
==14257== 
==14257== All heap blocks were freed -- no leaks are possible
==14257== 
==14257== For counts of detected and suppressed errors, rerun with: -v
==14257== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
4

4 に答える 4

3

sizeof(Object)この特定のケースでは、ほとんどの 32 ビット コンパイラでは 8 であるため、0 バイトを割り当てようとしている可能性があります。割り当てられるサイズが無効であるため、アドレスに書き込もうとするとmalloc(0)、アプリケーションが確実にクラッシュします。NULLNULL

しかし、4 バイトの割り当てに成功し、その中に 8 バイトを書き込もうとしたとします。シングル スレッド アプリケーションでは、おそらく問題なく動作するはずです。これは、未割り当てのメモリ領域に書き込みを行っているにもかかわらず、仮想メモリで失われたクレイジーなアドレスに正確に書き込んでいるとは限らないためです。

ただし、これを行う場合:

Object* a = (Object*)malloc(4);
Object* b = (Object*)malloc(4);

aとがb連続して割り当てられたことは、潜在的に真実です。つまり、ほとんどの 32 ビット コンパイラでは、書き込みは同じ値でa->number上書きb->messageされ、その逆も同様です。これは、どちらもメモリ内の同じスペースに情報を格納しようとするためです。

于 2013-04-01T05:32:25.017 に答える
1

sizeof に関するサブ質問に答えるには: sizeof は、使用している型に基づいて結果を生成します (C では、可変長配列には別のケースがあります)。あなたが書くなら

T* obj = malloc (any value);

sizeof (*obj) は *obj の型 (T である) を調べるだけで、T 型のオブジェクトのサイズを生成します。割り当てが失敗して obj が実際に NULL であるかどうか、またはより少ない数を割り当てたかどうかは問題ではありません。または T のサイズよりも多くのバイトがある場合、malloc をまったく呼び出さず、obj が初期化されていない変数であっても問題ありません。

于 2014-08-03T17:59:18.160 に答える
1

コンパイラとOSに依存します。多くの場合、最終的にクラッシュします。絶対にお勧めしません。バッファ オーバーフローが発生する可能性もあります。

于 2013-04-01T05:22:35.380 に答える