1.在C++ 程式中調用被 C編譯器編譯後的函數,為什麼要加 extern “C”?
答:C++語言支援函數重載,C語言不支援函數重載。函數被C++編譯後在庫中的名字與C語言的不同。假設某個函數的原型為: void foo(int x, int y);該函數被C編譯器編譯後在庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。由於編譯後的名字不同,C++程式不能直接調用C 函數。所以C++提供了C串連交換指定符號extern“C”來解決名字匹配問題。
2.考察記憶體
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
請問運行Test函數會有什麼樣的結果?
答:程式崩潰。函數參數都是局部變數,改變這些參數的值不會影響調用函數中的值。局部變數被儲存在棧中,函數返回時,棧被自動清空。malloc分配的記憶體不會被自動釋放,p指向自由儲存區中的記憶體塊,離開該指標的範圍時,該記憶體塊不會被自動歸還給自由儲存區。因為GetMemory並不能傳遞動態記憶體,Test函數中的 str一直都是 NULL。strcpy(str, "hello world");將使程式崩潰。
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
請問運行Test函數會有什麼樣的結果?
答:可能是亂碼。因為GetMemory返回的是指向“棧記憶體”的指標,該指標的地址不是 NULL,但其原現的內容已經被清除,新內容不可知。p[]數組為函數內的局部自動變數,在函數返回後,記憶體已經被釋放。這是許多程式員常犯的錯誤,其根源在於不理解變數的生存期。
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
請問運行Test函數會有什麼樣的結果?
答:(1)能夠輸出hello (2 )Test函數中也未對malloc的記憶體進行釋放。(3)GetMemory避免了試題1的問題,傳入GetMemory的參數為字串指標的指標,但是在GetMemory中執行申請記憶體及指派陳述式 p = (char *) malloc( num ); 後未判定記憶體是否申請成功,應加上: if ( *p == NULL ) { ...//進行申請記憶體失敗處理 }
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
請問運行Test函數會有什麼樣的結果?
答:篡改動態記憶體區的內容,後果難以預料,非常危險。因為free(str);之後,str成為野指標,if(str != NULL)語句不起作用。
3.指出以下代碼的問題
int main()
{
char a;
char *str=&a;
strcpy(str,"hello");
printf(str);
return 0;
}
答:沒有為str分配記憶體空間,將會發生異常。問題出在將一個字串複製進一個字元變數指標所指地址。雖然可以正確輸出結果,但因為越界進行內在讀寫而導致程式崩潰。