Suche senden
Hochladen
從 Singleton 談 constructor
•
Als PPTX, PDF herunterladen
•
18 gefällt mir
•
2,576 views
Luba Tang
Folgen
2012/10/25 新竹碼農
Weniger lesen
Mehr lesen
Melden
Teilen
Melden
Teilen
1 von 40
Jetzt herunterladen
Empfohlen
Three Optimization Tips for C++
Three Optimization Tips for C++
Andrei Alexandrescu
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
ktateish
C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0
信之 岩永
系統程式 -- 第 0 章
系統程式 -- 第 0 章
鍾誠 陳鍾誠
系統程式 -- 第 5 章 連結與載入
系統程式 -- 第 5 章 連結與載入
鍾誠 陳鍾誠
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版
Takuya Matsunaga
系統程式 -- 第 3 章
系統程式 -- 第 3 章
鍾誠 陳鍾誠
Windowsのパケットモニタ作成
Windowsのパケットモニタ作成
Shinichi Hirauchi
Empfohlen
Three Optimization Tips for C++
Three Optimization Tips for C++
Andrei Alexandrescu
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
ktateish
C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0
信之 岩永
系統程式 -- 第 0 章
系統程式 -- 第 0 章
鍾誠 陳鍾誠
系統程式 -- 第 5 章 連結與載入
系統程式 -- 第 5 章 連結與載入
鍾誠 陳鍾誠
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版
Takuya Matsunaga
系統程式 -- 第 3 章
系統程式 -- 第 3 章
鍾誠 陳鍾誠
Windowsのパケットモニタ作成
Windowsのパケットモニタ作成
Shinichi Hirauchi
Git flowの活用事例
Git flowの活用事例
Hirohito Kato
PHP Object Injection入門
PHP Object Injection入門
Yu Iwama
P2P Container Image Distribution on IPFS With containerd and nerdctl
P2P Container Image Distribution on IPFS With containerd and nerdctl
Kohei Tokunaga
系統程式 -- 第 1 章
系統程式 -- 第 1 章
鍾誠 陳鍾誠
系統程式 -- 第 1 章 系統軟體
系統程式 -- 第 1 章 系統軟體
鍾誠 陳鍾誠
Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料
Ryo Igarashi
系統程式 - 第二章
系統程式 - 第二章
鍾誠 陳鍾誠
Gitの便利ワザ
Gitの便利ワザ
ktateish
Clean Code
Clean Code
Dmytro Turskyi
YoctoをつかったDistroの作り方とハマり方
YoctoをつかったDistroの作り方とハマり方
wata2ki
続・モジュール / Introduction to C++ modules (part 2)
続・モジュール / Introduction to C++ modules (part 2)
TetsuroMatsumura
NEDIA_SNIA_CXL_講演資料.pdf
NEDIA_SNIA_CXL_講演資料.pdf
Yasunori Goto
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
Takuto Wada
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
Yoji Kanno
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム
信之 岩永
UEFI時代のブートローダ
UEFI時代のブートローダ
Takuya ASADA
Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16
Mitsuru Kariya
C++11 & C++14
C++11 & C++14
CyberPlusIndia
20170525 jsug バッチは地味だが役に立つ
20170525 jsug バッチは地味だが役に立つ
Yuichi Hasegawa
【BS2】.NET 6 最新アップデート
【BS2】.NET 6 最新アップデート
日本マイクロソフト株式会社
Keep your code clean
Keep your code clean
macrochen
C++工程实践
C++工程实践
Shuo Chen
Weitere ähnliche Inhalte
Was ist angesagt?
Git flowの活用事例
Git flowの活用事例
Hirohito Kato
PHP Object Injection入門
PHP Object Injection入門
Yu Iwama
P2P Container Image Distribution on IPFS With containerd and nerdctl
P2P Container Image Distribution on IPFS With containerd and nerdctl
Kohei Tokunaga
系統程式 -- 第 1 章
系統程式 -- 第 1 章
鍾誠 陳鍾誠
系統程式 -- 第 1 章 系統軟體
系統程式 -- 第 1 章 系統軟體
鍾誠 陳鍾誠
Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料
Ryo Igarashi
系統程式 - 第二章
系統程式 - 第二章
鍾誠 陳鍾誠
Gitの便利ワザ
Gitの便利ワザ
ktateish
Clean Code
Clean Code
Dmytro Turskyi
YoctoをつかったDistroの作り方とハマり方
YoctoをつかったDistroの作り方とハマり方
wata2ki
続・モジュール / Introduction to C++ modules (part 2)
続・モジュール / Introduction to C++ modules (part 2)
TetsuroMatsumura
NEDIA_SNIA_CXL_講演資料.pdf
NEDIA_SNIA_CXL_講演資料.pdf
Yasunori Goto
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
Takuto Wada
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
Yoji Kanno
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム
信之 岩永
UEFI時代のブートローダ
UEFI時代のブートローダ
Takuya ASADA
Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16
Mitsuru Kariya
C++11 & C++14
C++11 & C++14
CyberPlusIndia
20170525 jsug バッチは地味だが役に立つ
20170525 jsug バッチは地味だが役に立つ
Yuichi Hasegawa
【BS2】.NET 6 最新アップデート
【BS2】.NET 6 最新アップデート
日本マイクロソフト株式会社
Was ist angesagt?
(20)
Git flowの活用事例
Git flowの活用事例
PHP Object Injection入門
PHP Object Injection入門
P2P Container Image Distribution on IPFS With containerd and nerdctl
P2P Container Image Distribution on IPFS With containerd and nerdctl
系統程式 -- 第 1 章
系統程式 -- 第 1 章
系統程式 -- 第 1 章 系統軟體
系統程式 -- 第 1 章 系統軟體
Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料
系統程式 - 第二章
系統程式 - 第二章
Gitの便利ワザ
Gitの便利ワザ
Clean Code
Clean Code
YoctoをつかったDistroの作り方とハマり方
YoctoをつかったDistroの作り方とハマり方
続・モジュール / Introduction to C++ modules (part 2)
続・モジュール / Introduction to C++ modules (part 2)
NEDIA_SNIA_CXL_講演資料.pdf
NEDIA_SNIA_CXL_講演資料.pdf
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム
UEFI時代のブートローダ
UEFI時代のブートローダ
Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16
C++11 & C++14
C++11 & C++14
20170525 jsug バッチは地味だが役に立つ
20170525 jsug バッチは地味だが役に立つ
【BS2】.NET 6 最新アップデート
【BS2】.NET 6 最新アップデート
Ähnlich wie 從 Singleton 談 constructor
Keep your code clean
Keep your code clean
macrochen
C++工程实践
C++工程实践
Shuo Chen
C++11 smart pointers
C++11 smart pointers
chchwy Chang
改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法
crasysatan
C++11综述/新特性描述/Overview of C++11 New Features
C++11综述/新特性描述/Overview of C++11 New Features
Peien Luo
竞赛中C++语言拾遗
竞赛中C++语言拾遗
乐群 陈
系統架構設計 Android
系統架構設計 Android
健裕 潘
Lua 语言介绍
Lua 语言介绍
gowell
用Raspberry PI學Linux驅動程式
用Raspberry PI學Linux驅動程式
Stanley Ho
Object-Based Programming Part II
Object-Based Programming Part II
PingLun Liao
Java23种设计模式(总结)
Java23种设计模式(总结)
xuanlong282
認識 C++11 新標準及使用 AMP 函式庫作平行運算
認識 C++11 新標準及使用 AMP 函式庫作平行運算
建興 王
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
Johnny Sung
由一个简单的程序谈起――之二
由一个简单的程序谈起――之二
yiditushe
深入理解Andorid重难点
深入理解Andorid重难点
Bin Shao
Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)
Kris Mok
Rootkit 101
Rootkit 101
WEI CHIEH CHAO
iPhone,ios,Object-c基础入门
iPhone,ios,Object-c基础入门
Lucien Li
iPhone,ios,Object-C基础入门
iPhone,ios,Object-C基础入门
Lucien Li
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Justin Lin
Ähnlich wie 從 Singleton 談 constructor
(20)
Keep your code clean
Keep your code clean
C++工程实践
C++工程实践
C++11 smart pointers
C++11 smart pointers
改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法
C++11综述/新特性描述/Overview of C++11 New Features
C++11综述/新特性描述/Overview of C++11 New Features
竞赛中C++语言拾遗
竞赛中C++语言拾遗
系統架構設計 Android
系統架構設計 Android
Lua 语言介绍
Lua 语言介绍
用Raspberry PI學Linux驅動程式
用Raspberry PI學Linux驅動程式
Object-Based Programming Part II
Object-Based Programming Part II
Java23种设计模式(总结)
Java23种设计模式(总结)
認識 C++11 新標準及使用 AMP 函式庫作平行運算
認識 C++11 新標準及使用 AMP 函式庫作平行運算
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
炎炎夏日學 Android 課程 - Part1: Kotlin 語法介紹
由一个简单的程序谈起――之二
由一个简单的程序谈起――之二
深入理解Andorid重难点
深入理解Andorid重难点
Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)
Rootkit 101
Rootkit 101
iPhone,ios,Object-c基础入门
iPhone,ios,Object-c基础入门
iPhone,ios,Object-C基础入门
iPhone,ios,Object-C基础入门
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
從 Singleton 談 constructor
1.
認識 C++ constructor,從Singleton談起
Luba Tang 2010/5/11
2.
什麼是 singleton? • 在系統中
唯一 存在 的物件 – 唯一性 – 存在性 例子 1. 集中式資料庫 embeded dbm 2. 棋局中的棋盤 3. Register File
3.
傳統做法 – 全域變數 以棋盤為例子 •
在棋盤的 header file 中宣告為全域變數 Chess Board[20][20]; • 在 implementation file 中以外部變數使用 extern Chess Board[20][20];
4.
/***************************************** * board.h
* *****************************************/ class BoardType { }; static BoardType Board; /***************************************** * user.h * *****************************************/ #include “board.h” extern BoardType Board;
5.
用全域變數做 singleton 產生的問題 •
在多人同時開發之下,存在性與唯一性不 太容易保留 /***************************************** * user.h * *****************************************/ #include “board.h” extern BoardType Board; BoardType MyBoard = Board; MyBoard->setChess( black, 20 );
6.
用全域變數做 singleton 產生的問題 •
你真的確定你的型別一致嗎? // lib1.c // lib2.c unsigned int a; char a; // main.c extern a; 他到底是誰? [user@locahost]$ gcc –c ./lib1.c && gcc –c ./lib2.c && gcc –c ./main.c [user@locahost]$ gcc ./lib1.o ./lib2.o ./main.o
7.
Linker 解析 symbol
的順序 • Linker 用下列兩個 rules 解析 symbol – 不能存在兩個強符號 – 強符號 > 弱符號 – 大空間 > 小空間 • 在 gcc C compiler 當中 – 有初始值的 global variable 為強符號 – 沒有初始值的 global variable 為弱符號,屬於 COMMON variable處理 // lib1.c // lib2.c unsigned int a; char a; // main.c extern a; 是 unsigned int
8.
Global variable 的缺點 1.
不保證存在性 不保證唯一性 – 允許 copy, build, delete 2. 難移維護 – 使用到棋盤的物件都必須要知道棋盤的類別, 一旦棋盤類別被修改,就必須全部重新修改
9.
C++ 作法
提供唯一的進入點 class Board 如果 instance 沒有 new 過,就 new 一個新 { 的物件﹔否則就把之前 new 過的物件傳回去 public: static Board* self() { if( m_pInstance == 0 ) m_pInstance = new Board(); return m_pInstance; 真正的物件 } 必須要宣告為 static,以保證不會 private: 隨著特定物件而消失 Board(); static Board *m_pInstance; 前置宣告 }; 需要在實作檔中,前置宣告 instance,來初始化指標空間 Board *Board::m_pInstance = 0;
10.
Compiler 看 singleton C++
static member variable – 無論有沒有初始值,都視為 有初始值的 global variable,為強符號 – 強符號具有 linking view 上的唯一性 – 強符號具有 linking view 上的存在性
11.
問題 • 優點 –
不必再知道棋盤的類別,Board::self() 就可 以取得棋盤 • 缺點 – 我們只保證了 linking view,尚未保證 run- time behavior – 存在性尚未保證 delete Board::self(); // 合法
12.
C++ 作法 (2) class
Board { public: 將必要函式加入 private static Board* self(); Compiler 會自動幫類別加入這兩個 private: member function 到 public section中 強制加入到 private section Board(); ~Board(); private: static Singleton *m_pInstance; }
13.
問題 • 存在性確保了嗎? –
YES,無法任意 delete、new 物件 • 唯一性確保了嗎? – No,允許 copy assignment 和 copy constructor – Board b( *Board::self() ); // 合法,但不是我們想要的
14.
C++ 作法 (3) class
Board { public: 將必要函式加入 private Compiler 會自動幫類別加入這四個 static Board* self(); member function 到 public section中 強制加入到 private section private: Board(); ~Board(); Board( const Board& ); Board& operator=( const Board& ); private: static Singleton *m_pInstance; }
15.
背景知識 – static
local variable int Fun() { static int x = 100; 使用 static return ++x; 語意: 生成 function level 的全域變數 } 不同的執行期間,會看到同樣的記憶體 空間,同樣的變數
16.
Meyers’ Singleton
提供唯一的進入點 class Board static local variable 表示只有在執行第一次的 { 時候會被初始化,相當於之前 if-else 語法 public: static Board* self() { static Board Instance; return &Instance; } 真正的物件 private: 利用 static function 的特性,只有在函式被呼 Board(); 叫的時候才會有變數被生成 ~Board(); Board( const Board& ); 前置宣告 Board& operator=( const Board& ); 移除前置宣告,程式碼乾乾淨 }; 淨
17.
See Again –
Meyers’ Singleton class Board { public: static Board* self() { static Board Instance; return &Instance; } private: Board(); ~Board(); Board( const Board& ); Board& operator=( const Board& ); };
18.
Compiler 來看 Static
local variable normal local variable 稱做 auto-variable,會放在 stack or register 當中 – 通常會被 compiler optimization 消除 – Debugger 和 exception handling 需要有額外的 compensation code 來還原被削除的 auto-variable Static local variable 被放在 data/bss section 當中 – 大多數狀況下不會被 compiler optimization 消除 – gcc 不會消除 – 記憶體空間固定
19.
從 compiler 觀點看
Meyer’s Singleton class Board 何時執行該 { constructor? public: static Board* self() { static Board Instance; return &Instance; 阿就第一次執行的時候啊! } constructor 不過是另一個 private: function Board(); ~Board(); Board( const Board& ); Board& operator=( const Board& ); };
20.
Variable = storage
type + Duration C++ Storage – Static storage • 用 static 宣告出來的物件,包含 member variable – Automatic storage • Auto, register 或者 NOT static, extern 宣告出來的物件 – Dynamic storage • 用 new 做出來的物件 Storage Duration – Automatic duration • 用 register 或 auto 宣告出來的變數,相依於 scope – Dynamic duration • 從 new 開始,delete 結束 – Static duration • 從程式開始到結束
21.
Static storage initialization
的時機 在 standard 中如是說: Static storage 在所有其他 initialization 開始之前,就要先 zero initialization Non-local variable,不論任何 storage type,Static initialization 要在 dynamic initialization 之前 Zero initialization Initialization with constant expression Local static variable 的 initialization 比較複雜 – 允許 compiler 有自己的 implementation 1. 可以在 namespace scope 開始時 initialization 2. 可以在 first time control passes through the declaration 開始時幫忙 initialize GCC Compiler 當中這樣做: – Static storage 有值擺 .data – Static storage 沒值擺 .bss – Local static POD (C data type) 走 1 – 其他 local static variable 走 2
22.
See Again –
Meyers’ Singleton class Board { public: static Board* self() { static Board Instance(); ; 目前 gcc 不給過 return &Instance; } private: Board(); ~Board(); Board( const Board& ); Board& operator=( const Board& ); };
23.
新問題 – Dead
Reference Problem • 在系統結束時,設計不良的 singleton 很 有可能被消滅很多次,造成 segmentation fault
24.
Dead Reference Problem •
例子 – 三個 singleton 物件 – Board, Game, Log – 任何 singleton 發生問題,就會結束整個系統 – 所有物件的 destructor • Log::self()->printf( “Dead Mesg” ); • Clean up member variables
25.
26.
C++ 的static storage結束方式
- FILO • Static storage 的 duration是main之前到 main 之後 • Static storage 是先呼叫的後結束,在建立物件的時候 就決定了物件消滅的時間 • Game出問題 • Call Log::self() 1. Log::Log() 2. Log::printf() Game::Game() • Throw exception • Log::~Log(); Board::~Board() • Board::~Board() • Log::self()->printf(); Segmentation fault
27.
解法一 偵測出 Dead
Reference • 多加一個 static bool m_bDestroy 紀錄是 否被消滅過 • 在 Log constructor 中加判斷式,判斷是 否被摧毀過
28.
On Dead Singleton
(1/2) class Log 判斷為何 pointer 為 0 { onDeadReference() 會傳回 error public: create() 會建立新的 Log 物件 static Log* self() { if( m_pInstance == 0 ) { if( m_bDestroy ) onDeadReference(); else create(); } return m_pInstance; } private: static bool m_bDestory; Log* m_pInstance;
29.
On Dead Singleton private:
Meyers’ Singleton static void create() { 標準 constructor 寫法 static Log instance; m_pInstance = &instance; } static void onDeadReference() { throw std::runtime_error(”Dead Occurs”); } 避免 segmentation fault ~Singleton() { 傳回一個 exception,把問題 m_pInstance = 0; 丟出去 m_bDestory = true; } }; 不使用 delete 只需要把 pointer 設為 0,不可以 delete m_pInstance,系統會自動 destroy instance
30.
On Dead Singleton
(1/2) class Log 判斷為何 pointer 為 0 { onDeadReference() 會傳回 error public: create() 會建立新的 Log 物件 static Log* self() { if( m_pInstance == 0 ) { if( m_bDestroy ) onDeadReference(); else create(); } return m_pInstance; } Private instance pointer改為 private: static static bool m_bDestory; static Log* m_pInstance; Log* m_pInstance;
31.
問題 • 優點 –
不會發生 segmentation fault,由錯誤處理物 件負責處理 exception • 缺點 – 需要額外的錯誤處理物件,而錯誤處理物件 往往就是問題發生的元兇之一 (如本例的 Log 物件) – 沒有真正的解決問題,只做到認知問題而已
32.
Phoenix Singleton •
解決方法 – 希望在 onDeadReference() 中能夠重新初 始化 Log,讓死掉的 Log 復活,繼續工作 • 關於復活重要的四件事 1. 同樣的記憶體位置 2. 同樣的記憶體大小 3. 不同於死前的記憶體內容 4. 必須指定何時再去死一次
33.
背景資料 • Placement Operator
new() – 語法 new(address) class_name(); – 意義 1. 以 address 為起點,建立一個 class_name 的物件 2. 不會去註冊 atexit • atexit – 語法 int atexit( void (*pFun)() ); – 意義 註冊結束時應該執行哪一個 function, FILO stack
34.
Phoenix Singleton
取得已死的指標 private: create 雖然無法再取得新 static void 物件,但是可以取得死亡 onDeadReference() { 物件的指標 create(); new(m_pInstance) Log; 在相同位置建立新物件 atexit(killLog); 物件狀態會回覆到初始 化狀態,無記憶功能 m_bDestory = false; } 註冊死亡函式 static void killLog() { 其實是間接呼叫 destructor, m_pInstance->~Log(); 凡是有 operator new 就一定 要有 atexit } }; 死亡函式 間接呼叫destructor
35.
完整的 Phoenix Singleton
(1/3) class Log { public: static Log* self() { if( m_pInstance == 0 ) { if( m_bDestroy ) onDeadReference(); else create(); } return m_pInstance; }
36.
完整的 Phoenix Singleton
(2/3) private: static void onDeadReference() { create(); new(m_pInstance) Log; atexit(killLog); m_bDestory = false; } static void killLog() { m_pInstance->~Log(); } static void create() { static Log instance; m_pInstance = &instance; }
37.
完整的 Phoenix Singleton
(3/3) private: ~Log() { m_pInstance = 0; m_bDestory = true; } // constructor, copy constructor, and assignment … private: static bool m_bDestory; static Log* m_pInstance; }; // in cpp bool Log::m_bDestory = false; Log* Log::m_pInstance = 0;
38.
可能不是不死鳥,只是 32+ 命怪貓 atexit
只需要支援 “註冊 32 個 functions” GCC 好家在 Libiberty 提供 xatexit,沒有限制
39.
Singleton 優劣分析 優點
– 好用、好實作 – 比 global variable 多很多安全性 缺點 – 太好用,常會讓人忘記其毀滅關係上的困難 • 不可以偷懶! 要先規劃好生成與毀滅關係,最 後才能決定要不要使用 singleton。 • 通常規畫好之後,singleton數量會很少
40.
進階主題 • Thread-safe singleton
– Is Meyer’s singleton thread-safed? – If not, please implement one • Template singleton – Refer to template<typename T> llvm::ManagedStatic • Longevity singleton
Jetzt herunterladen