C++面試之GetMemory問題

題目一:

[cpp] view plain copy
  1. void GetMemory( char *p )  
  2. {  
  3.  p = (char *) malloc( 100 );  
  4. }  
  5.   
  6. void Test( void )   
  7. {  
  8.  char *str = NULL;  
  9.  GetMemory( str );   
  10.  strcpy( str, "hello world" );  
  11.  printf( str );  
  12. }  

【運行錯誤】傳入GetMemory(char* p)函數的形參爲字符串指針,在函數內部修改形參並不能真正的改變傳入形參的值。執行完

[cpp] view plain copy
  1. char *str = NULL;  
  2. GetMemory( str );  
後的str仍然爲NULL。編譯器總是要爲每個參數製作臨時副本,指針參數p的副本是_p,編譯器使_p=p。如果函數體內的程序修改了_p的內容,就導致參數p的內容作相應的修改,這就是指針可以用作輸出參數的原因。在本例中,_p申請了新的內存,只是把_p所指的內存地址改變了,但是p絲毫未變。所以GetMemory並不能輸出任何東西。事實上,每執行一次GetMemory就會泄露一塊內存,因爲沒有用free釋放內存。

題目二:

[cpp] view plain copy
  1. char *GetMemory( void )  
  2. {   
  3.  char p[] = "hello world";   
  4.  return p;   
  5. }  
  6.   
  7. void Test( void )  
  8. {   
  9.  char *str = NULL;   
  10.  str = GetMemory();   
  11.  printf( str );   
  12. }  
【運行錯誤】GetMemory中的p[]爲函數內的局部自動變量,在函數返回後,內存已經被釋放。這是很多程序員常犯的錯誤,其根源在於不理解變量的生存期。用調試器逐步跟蹤Test,發現執行str=GetMemory語句後str不再是NULL指針,但是str的內容不是“hello world”,而是垃圾。

題目三:

[cpp] view plain copy
  1. void GetMemory( char **p, int num )  
  2. {  
  3.  *p = (char *) malloc( num );  
  4. }  
  5.   
  6. void Test( void )  
  7. {  
  8.  char *str = NULL;  
  9.  GetMemory( &str, 100 );  
  10.  strcpy( str, "hello" );   
  11.  printf( str );   
  12. }  
【運行正確,但有內存泄露】題目三避免了題目一的問題,傳入GetMemory的參數爲字符串指針的指針,但是在GetMemory中執行申請及賦值語句
[cpp] view plain copy
  1. *p = (char *) malloc( num );  
後未判斷內存是否申請成功,應加上
[cpp] view plain copy
  1. if ( *p == NULL )  
  2. {  
  3.  ...//進行申請內存失敗處理  
  4. }  

也可以將指針str的引用傳給指針p,這樣GetMemory函數內部對指針p的操作就等價於對指針str的操作:

[cpp] view plain copy
  1. void GetMemory( char *&p)     //對指針的引用,函數內部對指針p的修改就等價於對指針str的修改  
  2. {  
  3.     p = (char *) malloc( 100 );  
  4. }  
  5.   
  6. void Test(void)  
  7. {  
  8.     char *str=NULL;  
  9.     GetMemory(str);  
  10.     strcpy( str, "hello world" );  
  11.     puts(str);  
  12. }  

題目四:

[cpp] view plain copy
  1. void Test( void )  
  2. {  
  3.  char *str = (char *) malloc( 100 );  
  4.  strcpy( str, "hello" );  
  5.  free( str );   
  6.  ... //省略的其它語句  
  7. }  
【運行正確,但有內存泄露】題目四與題目三存在同樣的問題,在執行malloc後未進行內存是否申請成功的判斷。此外,在free(str)後未置str爲空,導致可能變成一個“野指針”,應加上

[cpp] view plain copy
  1. str = NULL;  
題目三的Test函數中也未對malloc的內存進行釋放。

題目五:

[cpp] view plain copy
  1. char* GetMemory(int num)  
  2. {  
  3.     char* p = (char*)malloc(100);  
  4.     return p;  
  5. }  
  6.   
  7. void Test(void)  
  8. {  
  9.     char* str = NULL;  
  10.     str = GetMemory(100);  
  11.     strcpy(str, "hello");  
  12.     cout<<str<<endl;  
  13. }  
【運行正確】注意題目五和題目二的區別。雖然都是局部變量,但題目五用函數返回值來傳遞動態內存;而題目二return語句返回指向“棧”內存的指針,因爲該內存在函數結束時自動消亡。
題目六:

[cpp] view plain copy
  1. char* GetMemory(void)  
  2. {  
  3.     char* p = "hello world";  
  4.     return p;  
  5. }  
  6.   
  7. void Test(void)  
  8. {  
  9.     char* str = NULL;  
  10.     str = GetMemory();  
  11.     cout<<str<<endl;  
  12. }<strong>   </strong>  
【運行正確,但不合理】雖然Test運行不會出錯,但是函數GetMemory的設計概念卻是錯誤的。因爲GetMemory內的“hello world”是常量字符串,位於靜態存儲區,它在程序生命期內恆定不變。無論什麼時候調用GetMemory,它返回的始終是同一個“只讀”的內存塊。例如,如想執行

[cpp] view plain copy
  1. strcpy(str, "hello test");  
則程序會中斷,並提示內存錯誤。

題目七:

[cpp] view plain copy
  1. int* GetMemory(int* ptr)  
  2. {  
  3.     ptr = new int(999);  
  4.     return ptr;  
  5. }  
  6.   
  7. int main()  
  8. {  
  9.     int *ptr1 = 0, *ptr2 = 0;  
  10.     ptr1 = GetMemory(ptr2);  
  11.     if(ptr1) { cout<<*ptr1<<'\n'; } else { cout<<"ptr1 == NULL\n"; }  
  12.     if(ptr2) { cout<<*ptr2<<'\n'; } else { cout<<"ptr2 == NULL\n"; }  
  13.       
  14.     system("pause");  
  15.     return 0;  
  16. }  
程序輸出:

999

ptr2 == NULL

參考鏈接:

1. http://www.cppblog.com/mydriverc/articles/35389.html

2. http://blog.csdn.net/zhoubl668/article/details/6617130

3.http://blog.csdn.net/zhuxiaoyang2000/article/details/8084629


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章