今天在写代码的时候发现了一个很有意思的错误,出错的代码如下。
加入你的电脑里定义了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 阅读(2777)
评论(9) 编辑 收藏 引用 所属分类:
C、C++