看板 C_and_CPP 關於我們 聯絡資訊
不是在說明 overloaded operator new, c++ 書籍應該都會提到。 本範例是作業系統等級的程式碼, 在完成了 global/static object 的研究之後, 來 看看怎麼實作 new/delete, 在 c++ 若不能使用 new/delete, 好像說不過去。 測試方式: 在 linux compile 成 dos .com 檔, 然後放到 qemu/dos 上執行。 no_impl_new_delete.cpp 1 __asm__(".code16gcc\n"); 2 #include "io.h" 3 #include "obj.h" 4 5 typedef signed char s8; 6 typedef signed short s16; 7 typedef signed int s32; 8 9 typedef unsigned char u8; 10 typedef unsigned short u16; 11 typedef unsigned int u32; 12 13 #define BOCHS_MB __asm__ __volatile__("xchg %bx, %bx"); 14 15 extern int _start_ctors; 16 extern int _end_ctors; 17 18 void s16_print_int(int i, int radix); 19 void print_str(const char *s); 20 21 extern int obj_count; 22 23 24 const int SOME_BASE_ADDRESS = 0x500; 25 26 void myfree(void *ptr) 27 { 28 print_str("myfree\r\n"); 29 } 30 31 void *mymalloc(int size) 32 { 33 print_str("size: "); 34 s16_print_int(size, 10); 35 print_str("\r\n"); 36 static char mem[256]; 37 return mem; 38 } 39 52 53 extern "C" int cpp_main(void) 54 { 55 print_str("cpp_main\r\n"); 56 s16_print_int(obj_count, 10); 57 print_str("\r\n"); 58 59 Io *io_p = new Io; 60 const char *ver=__VERSION__; 61 io_p->print("io_p g++ version: "); 62 io_p->print(ver); 63 io_p->print("\r\n"); 64 delete io_p; 65 66 return 0; 67 } L59 和我們平常使用的 c++ new 用法一模一樣, new 會做類似 malloc 的動作, 先去要 一塊記憶體, 並呼叫 ctor, 可是在作業系統之前的程式, 根本沒有記憶體管理的程式碼 (記得我們沒有 c++ runtime 來幫我們做這件事情嗎?), 來看看編譯會怎麼樣? descent@debian-vm:dos_cpp$ make new_test.bin ld -m elf_i386 -static -Tcpp.ld -nostdlib -M -o new_test.elf cpp_init.o new_test.o io.o cpp_abi.o obj.o dos_io.o > new_test.elf.map new_test.o: In function `cpp_main': /home/descent/git/simple_os/cpp_runtime/global_object/dos_cpp/new_test.cpp:59: undefined reference to `operator new(unsigned int)' /home/descent/git/simple_os/cpp_runtime/global_object/dos_cpp/new_test.cpp:64: undefined reference to `operator delete(void*)' make: *** [new_test.elf] Error 1 呵呵, 果然有預期的錯誤, 要是沒錯誤反而令我害怕。訊息很容易理解, 沒定義 operator new, operator delete, 所以該怎麼辦? 不難, 自己定義就好了。 new_test.cpp L41 ~ L49 就提供了 operator new, operator delete, 比想像中還要簡 單吧! 這時候再編譯就沒問題了。有問題的是那個 mymalloc 要怎麼寫是吧? 這個的確是個問題, 得先搞定記憶體管理才能把這部份寫好, 一開始也困擾我許久, 因為 我這部份還沒做得很好, 不過我只想搞定 c++ runtime new/delete, 並不是要實作記憶體管理機制 (這個就不容易了), 所以想了個簡單的辦法來模擬 malloc 的行為。 L26, L31 的 mymalloc/myfree 應該很簡單, 簡單到不用說明吧? new_test.cpp 1 __asm__(".code16gcc\n"); 2 #include "io.h" 3 #include "obj.h" 4 5 typedef signed char s8; 6 typedef signed short s16; 7 typedef signed int s32; 8 9 typedef unsigned char u8; 10 typedef unsigned short u16; 11 typedef unsigned int u32; 12 13 #define BOCHS_MB __asm__ __volatile__("xchg %bx, %bx"); 14 15 extern int _start_ctors; 16 extern int _end_ctors; 17 18 void s16_print_int(int i, int radix); 19 void print_str(const char *s); 20 21 extern int obj_count; 22 23 24 const int SOME_BASE_ADDRESS = 0x500; 25 26 void myfree(void *ptr) 27 { 28 print_str("myfree\r\n"); 29 } 30 31 void *mymalloc(int size) 32 { 33 print_str("size: "); 34 s16_print_int(size, 10); 35 print_str("\r\n"); 36 static char mem[256]; 37 return mem; 38 } 39 40 // ref:http://goo.gl/T39BU8 41 void *operator new(unsigned int s) 42 { 43 return mymalloc(s); 44 } 45 46 void operator delete(void *p) 47 { 48 myfree(p); 49 } 50 51 extern "C" int cpp_main(void) 52 { 53 print_str("cpp_main\r\n"); 54 s16_print_int(obj_count, 10); 55 print_str("\r\n"); 56 57 Io *io_p = new Io; 58 const char *ver=__VERSION__; 59 io_p->print("io_p g++ version: "); 60 io_p->print(ver); 61 io_p->print("\r\n"); 62 delete io_p; 63 64 return 0; 65 } L57 new 發動時, L41 operator new 會被 c++ 編譯器傳入正確的 class size, 在 Io class 這個例子, size 是 4, 下圖便是在 dos 下的執行結果。 ( http://goo.gl/ov3WhK ) 比起 global/static object, operator new/delete 簡單到令我驚訝 (當然, 真的要處 理記憶體的分配與回收就沒那麼簡單了)。所以在作業系統之下寫 c++ 程式, c++ runtime library 做了不少辛苦的事情。 source code: https://github.com/descent/simple_os ( http://goo.gl/XDC9Iq ) commit 93e327234d153636e315721ca66f73df0e7c0887 cpp_runtime branch ref: http://wiki.osdev.org/C%2b%2b#The_Operators_.27new.27_and_.27delete.27 // 本文使用 Blog2BBS 自動將Blog文章轉成縮址的BBS純文字 http://blog2bbs.herokuapp.com/index.php // blog 原文: http://descent-incoming.blogspot.tw/2013/12/operator-newdelete.html -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 119.14.102.134
handsome616:超強.... 03/10 17:34