C++ 的 virtual function

在資結的作業裡,TA會先給出一套已經定義好的標頭檔(header file),並讓你繼承與實作內部函式(function)。而在他的標頭檔案裡,總是會在要重載的函式前加上 virtual 這個關鍵字,讓人實在無法忽略,於是特別寫了這篇來紀錄 virtual 這個字的實際效果與使用方式。


Visual Studio 常見的錯誤訊息與解決方案

由於在下修課緣故,教授所用的平台為Windows + Visual Studio2010
可是平常時我都是使用 Vim + Clang(LLVM) 所以對於這套 M$ 出品的 VS 頗難上手
遇到些丟出的訊息也是不知道怎麼處理
有時候網路上的解決方案也是無效,因此特別整理一篇疑難雜症集來紀錄
希望也能幫上遇到相同問題的人
請特別注意,以下事項皆針對課堂的作業所進行的解決方案,不一定是泛用型
(本文不定時更新,另外,如果有遇到什麼問題也歡迎一起來討論)

簡介 malloc 與 free (C語言)

這次要談的兩個C語言內建函式:malloc, free。

功能與用法:

首先,我們要先知道他的功能為何!
    malloc: 往memory_heap要記憶體
    free  : 釋放malloc的記憶體空間
另外,使用時別忘了包含 stdlib.h 這個標準函式庫。
(在 GCC 下編譯,如果忘記包含函式庫,大不了送你一個警告,自動幫你包入)

談到 memory_heap 這裡順便補充一下,以下是 memory 配置圖

通常我們在函式宣告(靜態)變數的時候,會被擺放在 stack 的這塊區域裡,這塊記憶體的部分會由系統掌握,這意味著我們不需要對他進行管理,系統會幫我們處理(像是離開函式後變數會被註銷等等)。

相對的, heap 則是用來做動態宣告,不過這區域必須由程式設計者自己管理,拿取多少記憶體,不用時就必須由程式設計者跟系統講說可以釋放,才會被註銷。

global 專門放置宣告在全域的變數,因為是獨立的區塊,所以我們會發現以往在區域變數(stack)沒辦法開的大陣列,在這裡就可以開大一點(不過正規的做法還是動態配置)

constant 專門存放常數的地方,這一區域有嚴格的封閉性,會禁止程式對他進行寫入

code 存放你寫的程式碼,用來執行用




 介紹記憶體結構完了,我們回歸正題,來看看今天的主角吧!


開始使用前,要先看一下他函式的原型,瞭解一下他是怎麼運行的。

malloc:
    void * malloc ( size_t size );
    傳入的參數為“想要”的空間,以 Byte 為單位,通常會使用 want_size*sizeof(Type) 來表示想要的空間,
    回傳值為 void 形態的指標,必須強制轉型成想要的形態。
    另外,如果函式執行成功回傳空間的起始位置,失敗則回傳NULL
    值得一提的是使用 malloc 的時候,這個函式要的記憶體會比你想的還大,
    多要的部分是拿來擺放跟這塊記憶體管理的相關資訊,
    (對源代碼有興趣的人請點文末的參考連結)

    使用時的範式如下:
    Type *ptr = (Type *) malloc ( want_size*sizeof(Type) );
  
    ptr 代表指向那塊記憶體的初始位置(概念上跟陣列一樣,使用上也雷同)
    這樣就是跟 heap 拿 want_size 個 Type 形態(Byte大小)的空間。


free:
    void free ( void * ptr );
    沒有回傳值,只是把指標傳進去,
    他會告訴 OS 說這塊記憶體不再使用,可以配置給別人
    (同樣的要如何清掉這塊記憶體也是 OS 的事)
    值得一提的是此函式是採用 call by value 的方式傳值,
    所以原本指標所指的位置並不會被清掉,僅僅是修改記憶體管理資訊而已。
    意味著就算使用完 free 還是有機會可以拿到那塊記憶體空間的資料,
    不過這就已經屬於不安全的使用了!


說了這麼多,我們來看範例:

簡單地索取與釋放

/*
 * malloc & free demo - True
 * 12/24/2012
 */


#include <stdio.h>
#include <stdlib.h>


const int size = 100; //配置一百個單位

int main(int argc, const char *argv[])
{

    // 整數陣列
    int *m_ptr = NULL;
    m_ptr = (int *) malloc (size*sizeof(int));
    // 檢查配置是否失敗
    if ( m_ptr == NULL ) {
        printf("Can not allocate memory!\n");
        exit(1);
    }

    // 字元陣列
    char *c_ptr;
    c_ptr = (char *) malloc (size*sizeof(char));
    // 檢查配置是否失敗
    if ( c_ptr == NULL ) {
        printf("Can not allocate memory!\n");
        exit(1);
    }

    // struct
    typedef struct {
        int a;
        float b;
    } List;
    List *s_ptr = (List *) malloc (size*sizeof(List));
    // 檢查配置是否失敗
    if ( s_ptr == NULL ) {
        printf("Can not allocate memory!\n");
        exit(1);
    }
  
    // 配置完後就可以開心的使用了~
    // 用法和陣列一模一樣,唯一要注意的是,不要動到指標,
    // 不小心指到奇怪的地方是很危險的

    // Important !
    // 一定要記得 free 掉用完的 memory !

    free(m_ptr);
    free(c_ptr);
    free(s_ptr);

    //End of Code

    return 0;
}


補充資料:
malloc的源代碼

淺談命令提示字元 (cmd) 的切換目錄指令 (cd)

由於做作業時,TA 給的輸入指令不是很清楚,
在絕對路徑與相對路徑的執行上有些困惑,
因此留下這篇筆記。

關於我自己

在資訊工程走著的孩子,有太多的事情不懂,太多的東西想瞭解,一頭栽入無遠弗屆的世界!

搜尋此網誌

總網頁瀏覽量

技術提供:Blogger.