今天在写代码的时候发现了一个很有意思的错误,出错的代码如下。
加入你的电脑里定义了JAVA_HOME这个环境变量,你能看出程序的输出结果是什么吗?
 1 #include <iostream>
#include <iostream>
 2 #include <assert.h>
#include <assert.h>
 3 #include <map>
#include <map>
 4 #include <string>
#include <string>
 5
 6 using namespace std;
using namespace std;
 7
 8 bool GetEnvByKey(string const &strKey, string &strValue)
bool GetEnvByKey(string const &strKey, string &strValue)
 9

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

 {
{
26 string strKey("JAVA_HOME");
    string strKey("JAVA_HOME");
27 string strValue;
    string strValue;
28 
    
29 if(GetEnvByKey(strKey, strValue))
    if(GetEnvByKey(strKey, strValue))
30
 
     {
{
31 cout<<strKey<<endl;
        cout<<strKey<<endl;
32 cout<<strValue<<endl;
        cout<<strValue<<endl;
33
34 map<string, string> mapEnvInfo;
        map<string, string> mapEnvInfo;
35 mapEnvInfo.insert(mapEnvInfo.end(), make_pair(strKey, strValue));
        mapEnvInfo.insert(mapEnvInfo.end(), make_pair(strKey, strValue));
36
37 cout<<mapEnvInfo.size()<<endl;
        cout<<mapEnvInfo.size()<<endl;
38 cout<<mapEnvInfo.begin()->first<<endl;
        cout<<mapEnvInfo.begin()->first<<endl;
39 cout<<mapEnvInfo.begin()->second<<endl;
        cout<<mapEnvInfo.begin()->second<<endl;
40 }
    }
41
42 return 0;
    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 阅读(2813) 
评论(9)  编辑 收藏 引用  所属分类: 
C、C++