プログラムは構文的には有効な C++ ですが、スタック オブジェクトのアドレスをヒープ アロケーターに渡すため、未定義の動作が発生します。通常、これは実行時にプログラムがクラッシュすることを意味します。
スタックとヒープは、プログラムを実行するプロセスに割り当てられる 2 つの異なるメモリ領域です。スタックは、引数とローカル変数を保持するために関数に入ると大きくなり、関数から戻ると自動的に縮小します。一方、ヒープは、必要に応じてメモリを取得できる別のアドレス領域であり、不要になったときに明示的に解放する必要があります。
ローカル変数のアドレスが realloc() に渡されると、メモリを解放して別の場所に割り当てようとする場合があります。アドレスはヒープからではなく、realloc() はヒープ上で動作するため、これは失敗します。ほとんどの場合、realloc() はアドレスがヒープからのものではないことを検出し、プログラムを中止します。
これとは別に、サンプル プログラムにはいくつかの論理エラーが含まれています。
char myString = NULL;
文字列ではなく文字を保持する変数を宣言します。C スタイルの文字列には type char*
、つまり char へのポインタがあります。
NULL
また、従来は無効なポインタに割り当てられていたアドレス 0 にchar が割り当てられます。プリプロセッサがNULL
リテラルに置き換えるため、これはコンパイルされ0
ます。実際には、char に 0 バイトを格納します。これは、慣例により、C スタイルの文字列のターミネータでもあります。
realloc(&myString, 5);
前述のように、スタック オブジェクトのアドレスをヒープ アロケーターに渡すため、これは違法です。この問題は、2 番目のコード例に残っています。
また、戻り値を破棄します。realloc()
新しいメモリが割り当てられたアドレスを返します。以前と同じアドレスではない可能性があります。NULL の場合もあります。これはrealloc()
、メモリが不足していることを示す方法です。
strncpy((char *)&myString, "test", 5);
これは正しいですが、キャストは冗長です。
あなたのプログラムのより正しいバージョンは次のとおりです。
#include <stdlib.h>
#include <string.h>
int main()
{
/* allocate space for, say, one character + terminator */
char* myString = (char*) malloc(2);
/* some code using myString omitted */
/* get more space */
myString = (char*) realloc(myString, 5);
/* write to the string */
strncpy(myString, "test", 5);
/* free the memory */
free(myString);
return 0;
}
C++ では、realloc() を完全に回避することをお勧めします。たとえば、次のようなものを使用できます。
#include <string>
int main()
{
std::string myString;
/* some code using myString */
myString = "test";
return 0;
}