今天在写代码的时候发现了一个很有意思的错误,出错的代码如下。
加入你的电脑里定义了JAVA_HOME这个环境变量,你能看出程序的输出结果是什么吗?
1#include <iostream>
2#include <assert.h>
3#include <map>
4#include <string>
5
6using namespace std;
7
8bool 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
24int 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 阅读(2768)
评论(9) 编辑 收藏 引用 所属分类:
C、C++