今天在寫代碼的時候發現了一個很有意思的錯誤,出錯的代碼如下。
加入你的電腦里定義了JAVA_HOME這個環境變量,你能看出程序的輸出結果是什么嗎?
1
#include <iostream>
2
#include <assert.h>
3
#include <map>
4
#include <string>
5
6
using namespace std;
7
8
bool GetEnvByKey(string const &strKey, string &strValue)
9

{
10
bool bRet = false;
11
12
assert(!strKey.empty());
13
14
size_t sizeValue = 0;
15
if(0 == getenv_s(&sizeValue, NULL, 0, strKey.c_str()))
16
{
17
strValue.reserve(sizeValue);
18
bRet = (0 == getenv_s(&sizeValue, const_cast<char*>(strValue.c_str()), sizeValue, strKey.c_str()));
19
}
20
21
return bRet;
22
}
23
24
int main( )
25

{
26
string strKey("JAVA_HOME");
27
string strValue;
28
29
if(GetEnvByKey(strKey, strValue))
30
{
31
cout<<strKey<<endl;
32
cout<<strValue<<endl;
33
34
map<string, string> mapEnvInfo;
35
mapEnvInfo.insert(mapEnvInfo.end(), make_pair(strKey, strValue));
36
37
cout<<mapEnvInfo.size()<<endl;
38
cout<<mapEnvInfo.begin()->first<<endl;
39
cout<<mapEnvInfo.begin()->second<<endl;
40
}
41
42
return 0;
43
}
先把你猜想的結果寫出來,然后再把代碼復制到VC里你試一下,看看到底輸出什么。你猜對了嗎?是不是輸出結果有點不太對?呵呵,經過調試代碼你發現錯誤了嗎?
錯誤就在
strValue.reserve(sizeValue);
bRet = (0 == getenv_s(&sizeValue, const_cast<char*>(strValue.c_str()), sizeValue, strKey.c_str()));
這兩行。
錯在這種使用strValue的方式,詳述如下:
strValue.reserve(sizeValue)這句代碼給strValue分配了sizeValue字節的內存,然后getenv_s又把從操作系統里取得的值賦給了strValue所代表的內存中,請注意strValue除了有指向字符串的內存數組,還有一個記錄該字符串中保存的字符數的一個變量_Mysize。上面的getenv_s執行后只是把字符串給賦值了,但是這個記錄字符串中字符個數的變量卻沒有賦值。下面的代碼需要使用這個變量才能進行輸出,而此時這個變量是0,所以strValue就沒有輸出。
經過上面的說明之后你肯定明白了上述代碼出錯的原因。為什么會出錯?是因為我們使用strValue的時候把它認為成了數組,所以就出錯了。本來strValue是一個對象,它具有各種方法,但是我們的使用方式強迫strValue脫下外衣,強迫它變成赤裸裸的字符串數組,這就是問題的發生根源。因此我們使用類對象的時候一定不能把類的外衣脫掉,讓類帶來的好處消失于無形。
posted on 2010-04-02 22:30
OnTheWay 閱讀(2781)
評論(9) 編輯 收藏 引用 所屬分類:
C、C++