malloc()
ファンクションは、少なくとも必要なメモリ容量を割り当てます。しかし、malloc()
が提供するメモリ量は、ここでの中心的な問題ではありません。
Cのプログラミング言語は、速度と効率を考慮して設計されているため、他の言語で行われている多くのチェックが行われていません。だからあなたは何か間違ったことをするプログラムを書くことができ、それはまだいくつかの状況下で動作し、他の状況では動作しません。
Cでは、ポインタはメモリ位置のアドレスです。 Cは、アドレスが有効なアドレスかどうかをチェックしません。 Cは、使用しようとしているメモリの量が正しいメモリ量であることを確認しません。
ここには、プログラムの注釈付きバージョンがあります。
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main() {
char *description; // create a variable that will contain the address of a character
clrscr();
// allocate an array of characters. the number of characters is 2 so this
// will allocate a minimum size memory area that will hold 2 characters.
// malloc() may round up the size or it may not but all you can count on
// is 2 characters in size.
description = malloc(2*sizeof(char));
// copy a constant string to the memory location pointed to by the variable
// description. the strcpy() function does not check on the limits of the
// memory. after the malloc() is done there is no size information available
// to strcpy() or any other of the C runtime library functions in the C Standard Library
// this is copying 11 characters plus the end of string for a total of 12 characters
// so to be correct the memory area pointed to by description should be at least
// 12 characters however we know from the malloc() above it is guaranteed to
// be only 2 characters so we are going past the memory area with this strcpy().
strcpy(description,"Hello there!");
// however we get lucky and it works anyway.
printf("%s",description);
// tell the memory allocation library that you are done with the memory and it
// can be used for something else now. the pointer will probably still be good
// for a while because the memory allocation, which gets its memory from the
// operating system, does not normally give any freed memory back to the OS.
// instead it normally just keeps it until the application terminates.
// as long as this freed memory is not used for something else, more than
// likely whatever you put there will remain there as is. however the moment
// the memory is given to something else, the values will change.
free(description);
printf("%s",description);
getch();
}
あなたが代わりにmalloc()
を使用してのスタック上の変数を使用していますあなたの変形である以下のサンプルプログラムをしようと何が起こっているかのようなアイデアを得ることができます。
Visual Studio 2013を使用してデバッグモードで実行すると、アプリケーションの終了時にメモリが上書きされるという警告が表示されます。私がリリースビルドを行い、それを実行すると、エラーはなく、次の出力が得られます。ご覧のとおり、strcpy()
関数は、隣接するメモリを上書きする文字をコピーしました。 Visual Studio 2013コンパイラのように、ダブルワード境界にメモリを配置すると、隣接するメモリ領域に文字列の最後の数文字しか表示されないように見えます。 Visual Studioは変数array2[]
をパディングし、割り当てられた次の変数がダブルワード境界になるようにしました。
Before
array1
array2
array3
description Hello there!
After
array1
array2 Hello there!
array3 ere!
私たちは、下記を上記のプログラムを変更する場合:
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main() {
char array1[12] = { 0 };
char array2[2] = { 0 };
char array3[12] = { 0 };
char *description;
int *values;
printf("Before\n array1 %s\n", array1);
printf(" array2 %s\n", array2);
printf(" array3 %s\n", array3);
description = &array2[0];
strcpy(description, "Hello there!");
printf("description %s\n", description);
printf("\nAfter\n array1 %s\n", array1);
printf(" array2 %s\n", array2);
printf(" array3 %s\n", array3);
description = malloc(8 * sizeof(char));
strcpy(description, "this");
printf("\n\nMalloc\n first description %p %s\n", description, description);
free(description);
values = malloc(1 * sizeof(int));
*values = 0;
printf(" pointer %p and value %d\n", values, *values);
printf(" second description %p %s\n", description, description);
}
をその後、我々は次の出力を取得します。この場合、malloc()
のにはint
の同じメモリ領域が割り当てられました。したがって、int
を修正したときに、description
の領域も変更されました。malloc()
は、次の割り当て領域を再利用したためです。
Before
array1
array2
array3
description Hello there!
After
array1
array2 Hello there!
array3 ere!
Malloc
first description 00944B28 this
pointer 00944B28 and value 0
second description 00944B28
malloc()
とfree()
を使用した場合、リソースの所有権原理
この例では、2つのルールを示しています。
malloc()
を割り当てると、必要なメモリ容量を超えることはありません。もっと必要な場合はrealloc()
の機能を見てください。
free()
を使用してメモリ領域を解放したら、そのポインタ値を再度使用しないでください。一度解放されると、メモリ領域を所有しなくなります。
malloc()
を使用すると、あなたが要求したメモリだけがメモリの所有者になります。 free()
を使用するときは、メモリの所有権を放棄し、もはやそれを所有していないため、使用しないでください。
あなたは足で自分を撃っています。これは、C言語が足で自分を撃つことを可能にする伝統とデザインの決定です。 – user3528438
Cのようなシステム言語では、自分自身を足で撃たなければなりません。解決策はそれをしないことです。 – DeiDei
上記のコメントをもっと鈍くするには、Cはあなたが何をしているのか知る必要があります。 – StoryTeller