C++一般的な面接問題-メモリ管理GetMemory()

4377 ワード

Getmemoryのいくつかの古典的なメモリに関する筆記試験問題:
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:公衆番号に注目し、技術を共有し、交流を学ぶ