接續以前寫的:
C取時間和指標使用上的一些眉角
C在編譯時帶入的變數
一般變數不太容易觀察生命週期,還好class在建立(new)和消滅(delete)時,會呼叫建構子(Constructor)和解構子(Destructor),在裡面加入log觀察,幫助理解加深記憶
Lambda運算式在C#很常見,但是C的Lambda功能更多也更複雜,
這裡先用來觀察建構子和解構子,更多的應用範例待以後的文章補充
#define STR(N) #N
#define XSTR(N) STR(N)
//__LINE__型態是%d,利用XSTR轉換成%s
#define _LINE_STR_ XSTR(__LINE__)
class MyClass
{
public:
MyClass()
{
printf("Constructor|%s|%s", _LINE_STR_, __FUNCTION__); //__FUNCTION__=="MyClass"
}
public:
~MyClass()
{
printf("Destructor|%s|%s", _LINE_STR_, __FUNCTION__); //__FUNCTION__=="~MyClass"
}
public:
static MyClass *Factory()
{
return new MyClass();
}
};
int main(const int argc, const char *argv[])
{
{ //_mf0只會活在大括弧內,離開大括弧時,會觸發解構子
const MyClass _mf0();
}
{ //Lambda練習1
auto lambda = [](void) { return new MyClass(); }; //離開大括弧時,不會觸發解構子
const MyClass *_mf1 = lambda();
delete _mf1; //觸發解構子
}
{ //Lambda練習2
std::function<MyClass *()> func = MyClass::Factory; //離開大括弧時,不會觸發解構子
const MyClass *_mf2 = func();
delete _mf2; //觸發解構子
delete _mf2; //程式當掉
}
return EXIT_SUCCESS;
}
Lambda練習2的彈性更廣,能當作變數傳遞給別的函式使用
多delete一次就會使程式當掉,會有類似以下的錯誤訊息,不同平台訊息可能不一樣,但程式都會當掉:
Exception has occurred.
Aborted
double free or corruption (fasttop): 0x0000000000646030 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x81299)[0x7ffff7052299]
當掉這點看來是沒救了,沒找到方法是能讓程式繼續往下執行的
結論C語言是有借有還的語言,借多少就要還多少,
還少一點(Memory Leak),程式可能可以跑久一點,直到吃光機器的記憶體形成大災難,
還多一點,立刻當掉沒得救
20240129補充Lambda練習3,紀錄
1.重複使用指標,忘記釋放記憶體的情況
MyClass *_mcPtr = NULL;
{ //區塊1
auto lambda = [](void) { return new MyClass(); };
_mcPtr = lambda();
}
{ //區塊2
std::function<MyClass *()> func = MyClass::Factory;
_mcPtr = func(); //重複使用指標,忘記釋放區塊1(Memory Leak)
//後來發現以下程式碼是不好的寫法,之後再補充修正
}