1. 程式人生 > >GetMemory函式詳解 (360面試題)

GetMemory函式詳解 (360面試題)

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

char *GetMemory(char *&p, int num)
{
p = (char *)malloc(sizeof(char)*num);

//p = new char[num];
return p;

}
int main(void)
{
char *str ;
GetMemory(str, 100);
strcpy(str, "hello");
cout << str << endl;
return 0;
}

//上面是一個正確的程式,下面是轉載的一些相關的知識

GetMemory錯誤講解(指標練習) 錯誤程式:

void GetMemory( char *p )
{
 p = (char *) malloc( 100 );
}
void Test( void )
{
 char *str = NULL;
 GetMemory( str );
 strcpy( str, "hello world" );
 printf( “%s”,str );
}

這個一個考驗對指標理解的題目,上面程式在執行之後:

1,呼叫GetMemory( str )後, str並未產生變化,依然是NULL.只是改變的str的一個拷貝的記憶體的變化   

2,strcpy( str, "hello world" );程式執行到這將產生錯誤。

3,new的時候有可能記憶體出錯,應該在*p = (char *) malloc( num ); 後判斷記憶體是否申請成功,應加上:
     if ( *p == NULL )
   {
     ...//進行申請記憶體失敗處理
   }

4,動態建立的記憶體沒釋放。

錯誤分析:

       錯認為 GetMemory(char   *p)中的 p “就是” GetMemory(str)中的str。但p“不是”str,它只是“等於”str 。
就象:   int   a   =   100;  
            int   b   =   a;       //   現在b等於a  
            b   =   500;         //   現在能認為a   =   500 ?     
顯然不能認為a   =   500,因為b只是等於a,但不是a! 當b改變的時候,a並不會改變,b就不等於a了。    因此,雖然p已經有new的記憶體,但str仍然是null  


GetMemory(str);             //把str傳進去,str是一個指標,而他實際上是一個int     
void   GetMemory(char   *p)     //   p是str的一個副本  
{  
p=(char   *)new   char[100];         //   p的值改變,但是str的值並沒有改變。  
}  
而雙重指標為什麼就可以了呢:  
GetMemory(&str);             //把str的地址傳進去      
void   GetMemory(char   **   p)     //   p是str地址的一個副本  
{  

    *p   =   (char   *)new   char[100];         //   p指向的值改變,也就是str的值改變。  
}

修改方法1:(推薦使用這種方法)

void GetMemory2(char **p)變為二級指標.
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(sizeof(char) * num);
}
void Test(void)
{
char *str=NULL;
GetMemory=(&str);
strcpy(str,"hello world");
printf(str);
}

修改方法2:

char *GetMemory()
{
char *p=(char *)malloc(100);
return p;
}
void Test(void){
char *str=NULL;
str=GetMemory();
strcpy(str,"hello world");
printf(str);
}

附錄A(相關資料)

試題5:
char *GetMemory( void )
{
 char p[] = "hello world";
 return p;
}

void Test( void )
{
 char *str = NULL;
 str = GetMemory();
 printf( str );
}
試題6:
void GetMemory( char **p, int num )
{
 *p = (char *) malloc( num );
}

void Test( void )
{
 char *str = NULL;
 GetMemory( &str, 100 );
 strcpy( str, "hello" );
 printf( str );
}
 試題7:

void Test( void )
{
 char *str = (char *) malloc( 100 );
 strcpy( str, "hello" );
 free( str );
 ... //省略的其它語句
}

解答:

試題5中
char p[] = "hello world";
return p;
的p[]陣列為函式內的區域性自動變數,在函式返回後,記憶體已經被釋放。這是許多程式設計師常犯的錯誤,其根源在於不理解變數的生存期。

試題6中
1、GetMemory避免了試題4的問題,傳入GetMemory的引數為字串指標的指標,但是在GetMemory中執行申請記憶體及賦值語句
*p = (char *) malloc( num );
後未判斷記憶體是否申請成功,應加上:
if ( *p == NULL )
{
 ...//進行申請記憶體失敗處理
}
2、試題6的Test函式中也未對malloc的記憶體進行釋放。

試題7中
    存在與試題6同樣的問題,在執行
char *str = (char *) malloc(100); 後未進行記憶體是否申請成功的判斷;另外,在free(str)後未置str為空,導致可能變成一個“野”指標,應加上: str = NULL;
 

  剖析:

  試題4~7考查面試者對記憶體操作的理解程度,基本功紮實的面試者一般都能正確的回答其中50~60的錯誤。但是要完全解答正確,卻也絕非易事。

  對記憶體操作的考查主要集中在:

  (1)指標的理解;

  (2)變數的生存期及作用範圍;

  (3)良好的動態記憶體申請和釋放習慣。

  再看看下面的一段程式有什麼錯誤:

swap( int* p1,int* p2 )
{
 int *p;
 *p = *p1;
 *p1 = *p2;
 *p2 = *p;
}

  在swap函式中,p是一個“野”指標,有可能指向系統區,導致程式執行的崩潰。在VC++中DEBUG執行時提示錯誤“Access Violation”。該程式應該改為:

swap( int* p1,int* p2 )
{
 int p;
 p = *p1;
 *p1 = *p2;
 *p2 = p;
}