今天寫code不小心犯了一個錯誤
函數LoadForm宣告如下
std::map<int, cData*> l_DataStack;
Form2^ l_Form2 = gcnew Form2(l_DataStack);
l_Form2.Show();
我期望的事情事Form2他可以拿到map的資料,然後在Form2的表單中,提供按鈕藉以修改或是更動資料。
Form2的建構子如下
private: std::map<int, cData*> *m_Data;
public:
Form2::Form2(std::map<int, cData*> &value)
{
m_Data = &value;
}
上面的建構子中m_Data將會紀錄value的map記憶體位置,然後又定義了一個按鈕事件如下
void button_event(object^ sender, eventargc^ e)
{
std::map<int, cData*>::iterator it = m_Data.begin();
it = (*m_Data).find(3); //假設找key=3的數值,不過這邊實際上是無法丟數值,需要用const int來送入
}
當Form2按下button的時候就會發生Crush,原因想了很久都沒找到問題。
後來解決辦法是直接把LoadForm底下的變數從local變數改成全域變數...
不過這樣又需要將原本的資料類型轉變成用指標的方式
std::map<int, cData*> *l_DataStack;
原因在於managed code和native code不同混用(如果將他宣告成global在編譯則會出現錯誤訊息)
全部用指標很單純而且很容易就確定你所指定的記憶體位置,不會因為做甚麼指標轉移而發生問題(除非你先釋放這塊記憶體)
但是不想用指標的話要怎麼解決?
方法很簡單,只要將LoadForm的Show改成ShowDialog即可。
原理是...
1. Show函數將視窗畫出後即往下一個指令執行,上述的LoadForm在畫出視窗後,即離開LoadForm的函數,因此Local變數l_DataStack的資料就會被釋放掉。(即使你在另一個類別有他的記憶體位置,資料因為被釋放了,所以當你再次使用他就會發生Crash)
2. ShowDialog函數則是將視窗畫出以後,直到你關閉式窗,才會將控制權歸還給父視窗。說清楚一點就是你沒關閉式窗,就不會在往LoadForm的下一個指令走,所以你的Local變數就不會被釋放掉。
比較之下我比較喜歡ShowDialog了@_@