如下程序各有何問題?
ios
***********************************************************************************************************************************
c++
1.程序員
void getmemory(char*p)面試
{
p=(char *) malloc(100);編程
}函數
int main()spa
{操作系統
char *str=NULL;
getmemory(str);指針
strcpy(str,「helloworld」);對象
printf("%s\n",str);
}
首先先回顧值傳遞與指針傳遞,引用傳遞的區別:
#include <iostream.h>
void swap(int x,int y)
{
int temp;
temp=x;
x=y;
y=temp;
}
void swap(int *x,int *y)
{
int temp;
temp=*x;
*x=*y;
*y=temp;
}
void swap(int& x,int& y)
{
int temp ;
temp=x;
x=y;
y=temp;
}
void main()
{
int x=5; int y=6;
swap(x,y);
*****5,6;值傳遞是在函數做用域中創建變量或對象的副本,一旦函數結束副本消失,不影響原值;
/*swap(&x,&y);*/
******6,5;指針傳遞傳遞的是變量或對象的地址,是在對變量或對象的原值進行操做,會改變原值;
/*swap(x,y);*/
*******6,5;引用傳遞形式如值傳遞但效果同指針傳遞,是原來變量或對象的別名,是在對變量或對象的原值進行操做
cout<<「交換後:x=」<<x;
cout<<「y=」<<y<<endl;
}
題1就如同是值傳遞,對原值str不起任何影響,str 依舊是NULL,每運行一次就有一塊內存泄露,因此當函數的參數是一個指針,不要期望用該指針去申請動態內存。
*********************************************************************************************************************************
2.
void getmemory(char*p)
{
p=(char *) malloc(100);
strcpy(p,「helloworld」);
}
int main( )
{
char *str=NULL;
getmemory(str);
printf(「%s/n」,str);
free(str);
return 0;
}
有題1 可知道,str最終沒有分配到內存,free(str)是危險操做;
************************************************************************************************************************************
3.
void *getmemory(void)
{
char p[]="hello";
return p;
}
int main()
{
char *str=NULL;
str=getmemory();
printf("%s\n",str);
}
不要用return 語句返回指向「棧內存」的指針,由於該內存在函數結束時自動釋放,str指向的地址原先內容不可知,現有內容不清楚,輸出亂碼
注意:函數的返回值是指針類型的,檢查是靜態內存指針仍是堆內存指針仍是棧內存指針,棧內存指針是絕對要不得滴
************************************************************************************************************************************
4.
void getmemory(char** p,int num)
{
*p=(char*)malloc(num);
}
int main()
{
char *str=NULL;
getmemory(&str,100);
strcpy(str,「helloworld」);
printf("%s\n",str);
}
用指向指針的指針(二級指針)申請動態內存,(c中經常使用的指針傳遞)該函數能正常輸出helloworld,可是忘記free()會形成內存泄露;
注意:(指針傳遞,一級指針)函數中只能對指針的指向的值(*p)進行修改,
而不能修改指針地址(改變p值,*p不變)!
例:
void fun(int *p)
{
int b=100;
p=&b; // b的地址並無被返回
}
程序4:
void fun(int *p)
{
*p=100; // okay
}
(函數要求修改指針參數的地址,必須使用指針的指針!(二級指針)
(那麼c++中能夠運用引用傳遞來動態申請內存void getmemory(char*& p,int num))
********************************************************************************************************************************
5.
int main()
{
char* str=(char*)malloc(100);
strcpy(str,「hello」);
free(str);
if(str!=NULL)
{
strcpy(str,「world」);
printf(str);
}
return 1;
}
str 所指的內存被釋放,可是str 所指的地址仍然不變,if(str!=NULL)沒有任何做用。
str變成野指針,「野指針」不是NULL 指針,是指向「垃圾」內存的指針,
「野指針」的成因主要有兩種:
(1)指針變量沒有被初始化。任何指針變量剛被建立時不會自動成爲NULL 指針,它
的缺省值是隨機的,它會亂指一氣。因此,指針變量在建立的同時應當被初始化,要麼
將指針設置爲NULL,要麼讓它指向合法的內存。例如
char *p = NULL;
char *str = (char *) malloc(100);
(2)指針p 被free 或者delete 以後,沒有置爲NULL,讓人誤覺得p 是個合法的指針。
(3)指針操做超越了變量的做用範圍。這種狀況讓人防不勝防,示例程序以下:
class A
{
public:
void Func(void){ cout << 「Func of class A」 << endl; }
};
void Test(void)
{
A *p;
{
A a;
p = &a; // 注意 a 的生命期
}
p->Func(); // p 是「野指針」
}
函數 Test 在執行語句p->Func()時,對象a 已經消失,而p 是指向a 的,因此p 就成了「野指針」。
*********************************************************************************************************************************
內存管理:
中軟面試題:
內存有哪幾種存儲組織結構.請分別加以說明《來自高質量c/c++編程》
1.從靜態存儲區域分配:
內存在程序編譯時就已經分配,這塊內存在程序整個運行過程都存在。(全局變量,static變量)
2.在棧上建立:
函數內部的局部變量在棧上建立,函數結束後,這些存儲單元會自動釋放。 分配內存效率高,可是分配內存容量有限。
3.從堆上分配(動態內存分配):
由malloc()和new()手動分配內存,由delete(),free()手動釋放內存空間。內存空間由程序員本身決定,可分配的內存容量大。
注意:
malloc申請的是連續的一塊內存,當返回NULL表示內存申請失敗,用if(NULL!=p)驗證, 如果內存分配失敗用exit(1),終止整個程序; 棧出現內存泄露狀況一般是由沒有回收垃圾資源,沒有進行內存釋放引發的
free(p);斬斷了指針與這塊內存的關係,
雖然指針P仍然保存原來的地址,可是已經失去了對那塊內存的控制權,一樣,對應的那塊內存雖然內容存在,不過,已經沒法利用其中的數據,成爲垃圾文件。對於每次malloc()只能有一次free(),若free()兩次會出錯,除非原指針指向NULL
全局變量和局部變量有什麼區別?是怎麼實現的?操做系統和編譯器是怎麼知道的?
生命週期不一樣:全局變量隨主程序建立和建立,隨主程序銷燬而銷燬;局部變量在局部函數內部,甚至局部循環體等內部存在,退出就不存在;內存中分配在全局數據區。
使用方式不一樣:經過聲明後全局變量程序的各個部分均可以用到;局部變量只能在局部使用;分配在棧區。
操做系統和編譯器經過內存分配的位置來知道的,
全局變量分配在全局數據段而且在程序開始運行的時候被加載。局部變量則分配在堆棧裏面。
fmoonstar 更新至2011.11.4