今天寫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了@_@

創作者介紹

StreamWhite

teexit1224 發表在 痞客邦 PIXNET 留言(0) 人氣()