全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2446
推到 Plurk!
推到 Facebook!

Variant 和 const wchar_t* 的 bug?

 
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2006-07-25 21:54:49 IP:61.229.xxx.xxx 訂閱

最近用bcb寫com元件,發現其中Variant型別與wchar_t*的轉換有些問題(怪怪的)。

for example:

void __fastcall TForm1::Button1Click(TObject *Sender)
{

Variant v1(L"NONO");

ShowMessage(v1.AsType(varString));

}

show出來的內容是對的,但在ide 下run卻在離開function時出現了錯誤,好像無法正常的relase一些東西。

若把程式改成

void __fastcall TForm1::Button1Click(TObject *Sender)
{

Variant v1(WideString(L"NONO"));

ShowMessage(v1.AsType(varString));

}

可以正常的return。這問題在寫com時的症狀是你無法從com傳出字串,但若在Variant的建構式上先經由widestring建構,再copy至variant就很正常。有點脫褲放屁,但一定要這樣。不知道是什麼問題? 看了相關的variant 建構式中,by value 的方式裡的確是有Variant(wchar_t* const src);可為何一定要經過widestring穩含轉換一次?

不知大家有什麼看法?

------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2006-07-26 00:43:45 IP:61.229.xxx.xxx 訂閱

打了二次好長的解答研究報告…但都在要傳出的時候不見了…session time out? back 也找不回資料…
這討論版要稍bug test一下,不然…就只能在notepad下打好在貼了! :<

打累了,把最後的答案精簡的講一下,想知道深入的請在post出來。

答案: Variant 複載建構式中的 wchar_t* 不是真的要傳入 wchar_t*的指標,而是BSTR。因為這個類別在解構的時候可能用到SysFreeString 這個api。

WideString中的方法c_bstr( )傳回的也非code completion上所寫的wchar_t* 而是正統的BSTR。

BSTR與wchar_t*所指的資料內容都是一樣的型別,wchar_t。然而BSTR所配置出來的memory,在字串前有四個byte記載著字串的總byte數。這是二者的不同。以下的程式証明…

WideString bs = L"我是蕭沖";
BSTR s = bs.c_bstr();
char **p=(char**)&s;
unsigned long *z=(unsigned long *)(*p-4);
unsigned long j=*z; // 取字串前的四個byte
SysFreeString(s);
ShowMessage(j);

得到8,即字串總長是8byte。

結論: Variant中的建構式複載wchar_t* 不能放入自己用陣列或是new或是malloc等配發的wchar_t * 指標! 不要被騙了!!

這是很重大的發現!!

蕭沖

qs.xiao@gmail.com

------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2006-07-26 00:47:14 IP:61.229.xxx.xxx 訂閱

最上面的問題測式需要在 IDE 下run才看得出來有錯誤!

即問題是潛藏著的。而我的os是XP home,若直接run是正常的。xp 會ignore一些小錯誤。之前我曾某個程式在2k上跑就有問題,但在xp上跑就"正常"。

------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2006-07-26 00:51:39 IP:61.229.xxx.xxx 訂閱
程式有點小貼錯… 重貼 (重打太多次,有點心浮 xp)

WideString bs = L"我是蕭沖";
BSTR s = bs.c_bstr(); // 改寫成 wchar_t* s = bs.c_bstr() 也是一樣的
char **p=(char**)&s;
unsigned long *z=(unsigned long *)(*p-4);
unsigned long j=*z; // 取字串前的四個byte
ShowMessage(j);
------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2010-11-05 14:18:51 IP:210.64.xxx.xxx 訂閱
事隔4年多了,又發覺一個WideString的問題。平常很少機會用到它,所以都沒仔細的去了解。

這次發現的問題:


[code cpp]
WideString ws(L"\x1234");
WideString ws2(L"good");
ws = "select * from";
ws = ws2.c_bstr();
ws = L"select * from 222";
[/code]

當執行最後一行時,就一定會出錯。可是好像直覺是可以的。查了help檔再次了解到,原來 = 的複載裡沒有定義 wchar_t* 的型別。 可是為什麼compile時是正確的,並沒有什麼型別錯誤。於是叫出cpu來debug。發現,原來compiler會自動的加一些料,它的確就是使用了 wchar_t* 的 = operator。疑? 這個型別在help檔裡根本沒提到。為何有這個藏著的方法呢? 再深入的去了解… 唉呀,原來這個隱藏的 方法 是用在 bstr 的。所以你看上面的程式碼,當ws = ws2.c_bstr(); 這行就不會出錯。但搞一個正統的wchar_t* 的帶入就掛點。

所以,我又回憶起以前有類似追個這樣的事…就找到我篇了。人老了還是會忘了些東西… 結論,要使用 WideString 的 = 複載方法時,一定要:

WideString ws;
ws = WideString(L"hello");

而不能
ws = L"hello";

因為第二種compiler不會說型別有誤(因為有內藏),但run下去就死。

最後還是一句話:
在bcb裡, wchar_t * 與 bstr 常常以同樣的宣告出現,但實則不一樣。要注意! 所見的wchar_t* 的參數 常常很有可能是指bstr !

------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
系統時間:2017-12-14 23:04:43
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!