這種錯誤常有人會犯:在副函式裡面使用指標配置了一個新的記憶體空間,最後把這個指標傳回給主程式。為什麼不行?如果這個問題不知道答案的話,請回到 CallByValue 詳細看一遍再回來看解說...

先看以下的 code 再做說明

原始碼

// ====================================
// FileName: PtrFunc.cpp
// Author  : Edison.Shih.
// Complier: VC 2008

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DemoString        "Edison.Shih."
#define LEN               strlen(DemoString)
#define TEST_NUM        50000
#define TEST_LOOP        500
// ====================================
char* Error1()
{
     char String[] = DemoString;    // warning
     return String;
}

void Error2(char *String)
{
     strcpy(String, DemoString);   // run-time error
}

void Error3(char *String)
{
     String = (char*)malloc(sizeof(char)*LEN);
     strcpy(String, DemoString);
}

char* CareFor(char *String)
{
     String = (char*)malloc(sizeof(char)*(LEN*TEST_NUM));
     strcpy(String, DemoString);
     return String;
}

// ====================================
int main(int argc, char **argv)
{
     char *ptr;
     int i=0;

     ptr = NULL, ptr = Error1(),     printf("%s(len=%d)\n", ptr, strlen(ptr));
 //      ptr = NULL, Error2(ptr),        printf("%s(len=%d)\n", ptr, strlen(ptr));
     ptr = NULL, Error3(ptr),        printf("%s\n", ptr); // strlen(ptr) has run time error.

     system("pause");
     for(i=0; i<TEST_LOOP; i++)        
          ptr = NULL, ptr = CareFor(ptr), printf("%s(len=%d)\n", ptr, strlen(ptr)), free(ptr);
     return 0;
}

 

char *Error1() : 在副函式中配置變數,離開副函式後什麼都沒有

void Error2(char *String):原本在主程式裡面並沒有配置 String 該有的記憶體空間,導致想要複製字串時沒有實體空間可複製,這將造成 run-time error.

void Error3(char *String):傳進一個指標後,先在副函式裡面做配置的動作,到最後所有的配置動作也都只是在記憶體,最後回傳時,String 仍為 NULL。

char* CareFor(char *String):這種用法真的要小心,一般而言我們用到 malloc 時,必須要有能力進行 free 的動作才有意義。這個函式它的回傳值是正確沒錯,但最後應注意的是,最後「一定」要有另一個指標去接它,且一次 malloc,就要對到一次 free。

如上程式碼所述,在 loop 裡,紅色的 CareFor 已用 malloc 進行了配置,最後也要再用 free 將記憶體釋放。

一般而言,我比較建議初學者,所有配置動態記憶體的動作都在主函式裡面配置完畢,再呼叫副函式處理、運算配置好的動態空間。若有能力寫出一段副函式,可以隨心所欲配置各種資料型態之二維陣列 (且效率要好),倒是可考慮包成副函式。

如果硬要在副函式裡面配置記憶體空間的話,提供下面方式給各位參考...如果有其它方式,也歡迎提出


void test(char **Ptr2)
{
        *Ptr2 = (char*)malloc(sizeof(char*)*LEN*TEST_NUM);
        strcpy(*Ptr2, "Edison.Shih.");
}

main(){
...
...
        char **ptr2 = &ptr;
        test(ptr2);
        printf("%s\n", ptr);
        free(*ptr2);
}

如果本身指標不行的話…換個角度…直接再用指標的指標去控制!因為這真的很麻煩,所以還是建議,要配置動態記憶體的話,還是先在 main() 裡面配置完後,再交給副函式做運算處理…

以上.指標特輯到此告一段落,下一篇將整理所有的目錄

若對於指標或是C\C++有問題,歡迎一起討論指教

arrow
arrow
    全站熱搜

    Edison 發表在 痞客邦 留言(2) 人氣()