C++一般的な面接問題-メモリ管理GetMemory()
Getmemoryのいくつかの古典的なメモリに関する筆記試験問題:
【
実行エラー
]GetMemory(char*p)関数に入力されたパラメータは文字列ポインタであり、関数内部でパラメータを変更することは、入力されたパラメータの値を本当に変更することはできません.実行完了
後のstrはNULLのままです.
本質:コンパイラは常に各パラメータに一時的なコピーを作成し、ポインタパラメータpのコピーは_p,コンパイラ使_p=p.関数内のプログラムが変更されたら_pの内容は、パラメータpの内容を相応に修正することになり、これがポインタが出力パラメータとして使用できる理由である.この例では_pは新しいメモリを申請しましたが、ただ_pが指すメモリアドレスは変更されましたが、pは少しも変わりません.だからGetMemoryは何も出力できません.実際、GetMemoryを実行するたびにメモリが漏洩します.freeでメモリを解放していないためです.
【
実行エラー
]GetMemoryのp[]は関数内のローカル自動変数であり、関数呼び出しが返された後、メモリは解放された.だから印刷されたデータは私たちが印刷を要求したデータではありませんが、戻ってきたポインタが指すアドレスは一定です.これは多くのプログラマーがよく犯す誤りであり,その根源は変数の生存期間を理解していないことにある.テスターをデバッガで逐次追跡すると、str=GetMemory文を実行するとstrはNULLポインタではありませんが、strの内容は「hello world」ではなく、ゴミです.
【
正しく動作していますが、メモリの漏洩があります.
】
タイトル1の問題を回避し、GetMemoryに入力されたパラメータは文字列ポインタのポインタであるが、GetMemoryでは申請および付与文を実行する
メモリが正常に申請されたかどうかを判断していない場合は、
ポインタstrの参照をポインタpに渡すこともでき、GetMemory関数の内部のポインタpに対する操作はポインタstrに対する操作に等しい.
【
正しく動作していますが、メモリの漏洩があります.
】
と
同様の問題があり、mallocを実行した後、メモリが申請に成功したかどうかの判断は行われなかった.また、free(str)後にstrを空にしないと、「野ポインタ」になる可能性があります.
のTest関数でもmallocのメモリは解放されていません.
【正しく動作する】との違いに注意してください.いずれもローカル変数ですが、は関数の戻り値で動的メモリを渡します.
return文は、関数の終了時に自動的にメモリが消滅するため、スタックメモリへのポインタを返します.
【
運行は正しいが合理的ではない
]Testの実行にはエラーはありませんが、関数GetMemoryの設計概念はエラーです.GetMemory内の「hello world」は定数文字列であるため、静的ストレージ領域に位置し、プログラムのライフサイクル中は一定である.GetMemoryは、いつ呼び出されても、常に同じ読み取り専用メモリブロックを返します.たとえば、実行したい場合
プログラムが中断し、メモリエラーが表示されます.
プログラム出力:
999
ptr2 == NULL
PS:公衆番号に注目し、技術を共有し、交流を学ぶ
void GetMemory( char *p )
{
p = (char *) malloc( 100 );
}
void Test( void )
{
char *str = NULL;
GetMemory( str );
strcpy( str, "hello world" );
printf( str );
}
【
実行エラー
]GetMemory(char*p)関数に入力されたパラメータは文字列ポインタであり、関数内部でパラメータを変更することは、入力されたパラメータの値を本当に変更することはできません.実行完了
char *str = NULL;
GetMemory( str );
後のstrはNULLのままです.
本質:コンパイラは常に各パラメータに一時的なコピーを作成し、ポインタパラメータpのコピーは_p,コンパイラ使_p=p.関数内のプログラムが変更されたら_pの内容は、パラメータpの内容を相応に修正することになり、これがポインタが出力パラメータとして使用できる理由である.この例では_pは新しいメモリを申請しましたが、ただ_pが指すメモリアドレスは変更されましたが、pは少しも変わりません.だからGetMemoryは何も出力できません.実際、GetMemoryを実行するたびにメモリが漏洩します.freeでメモリを解放していないためです.
char *GetMemory( void )
{
char p[] = "hello world";
return p;
}
void Test( void )
{
char *str = NULL;
str = GetMemory();
printf( str );
}
【
実行エラー
]GetMemoryのp[]は関数内のローカル自動変数であり、関数呼び出しが返された後、メモリは解放された.だから印刷されたデータは私たちが印刷を要求したデータではありませんが、戻ってきたポインタが指すアドレスは一定です.これは多くのプログラマーがよく犯す誤りであり,その根源は変数の生存期間を理解していないことにある.テスターをデバッガで逐次追跡すると、str=GetMemory文を実行するとstrはNULLポインタではありませんが、strの内容は「hello world」ではなく、ゴミです.
void GetMemory( char **p, int num )
{
*p = (char *) malloc( num );
}
void Test( void )
{
char *str = NULL;
GetMemory( &str, 100 );
strcpy( str, "hello" );
printf( str );
}
【
正しく動作していますが、メモリの漏洩があります.
】
タイトル1の問題を回避し、GetMemoryに入力されたパラメータは文字列ポインタのポインタであるが、GetMemoryでは申請および付与文を実行する
*p = (char *) malloc( num );
メモリが正常に申請されたかどうかを判断していない場合は、
if ( *p == NULL )
{
...//
}
ポインタstrの参照をポインタpに渡すこともでき、GetMemory関数の内部のポインタpに対する操作はポインタstrに対する操作に等しい.
// , p str
void GetMemory( char *&p)
{
p = (char *) malloc( 100 );
}
void Test(void)
{
char *str=NULL;
GetMemory(str);
strcpy( str, "hello world" );
puts(str);
}
void Test( void )
{
char *str = (char *) malloc( 100 );
strcpy( str, "hello" );
free( str );
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
【
正しく動作していますが、メモリの漏洩があります.
】
と
同様の問題があり、mallocを実行した後、メモリが申請に成功したかどうかの判断は行われなかった.また、free(str)後にstrを空にしないと、「野ポインタ」になる可能性があります.
str = NULL;
のTest関数でもmallocのメモリは解放されていません.
char* GetMemory(int num)
{
char* p = (char*)malloc(100);
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory(100);
strcpy(str, "hello");
cout<<str<<endl;
}
【正しく動作する】
return文は、関数の終了時に自動的にメモリが消滅するため、スタックメモリへのポインタを返します.
char* GetMemory(void)
{
char* p = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
cout<<str<<endl;
}
【
運行は正しいが合理的ではない
]Testの実行にはエラーはありませんが、関数GetMemoryの設計概念はエラーです.GetMemory内の「hello world」は定数文字列であるため、静的ストレージ領域に位置し、プログラムのライフサイクル中は一定である.GetMemoryは、いつ呼び出されても、常に同じ読み取り専用メモリブロックを返します.たとえば、実行したい場合
strcpy(str, "hello test");
プログラムが中断し、メモリエラーが表示されます.
int* GetMemory(int* ptr)
{
ptr = new int(999);
return ptr;
}
int main()
{
int *ptr1 = 0, *ptr2 = 0;
ptr1 = GetMemory(ptr2);
if(ptr1) { cout<<*ptr1<<'
'; } else { cout<<"ptr1 == NULL
"; }
if(ptr2) { cout<<*ptr2<<'
'; } else { cout<<"ptr2 == NULL
"; }
system("pause");
return 0;
}
プログラム出力:
999
ptr2 == NULL
PS:公衆番号に注目し、技術を共有し、交流を学ぶ