使用c/c++指针时,一定要区分清楚指针所占用的内存和指针所指向的内存。指针一经定义,无论初始化与否,系统将为其分配一个4字节(32位系统,另外64位系统为8字节)的内存,即为指针所占用的内存。该内存存放指针所指向的变量的地址,此地址对应一个内存,即为指针所指向的内存。对指针进行操作,也就分为对指针所占用的内存进行操作和对指针所指向的内存进行操作两种情况。前者是直接对内存进行操作,形同与普通变量的情况,一般不容易出错;后者是间接对内存进行操作,如果此内存由于各种原因而不可读或不可写(例如系统占用的内存、未分配的内存、空内存、释放后的内存、不可写或不可读的内存、越界的内存等等),那么就会出现错误。下面讨论的均是由于对指针所指向的内存进行不正确操作而产生的问题:
1. 引用未初始化的指针(此时指针所指向的内存是随机的,通常指向系统占用的或未分配的内存,不可读写)
例如:
int main(){
char* pstr;
strcpy(pstr,"hello world!");
cout<<pstr<<endl;
system("pause");
return 1;
}
运行程序将出现:
2. 引用空指针(此时指针所指向的内存是空内存或零内存,不可读写)
例如:
int main(){
char* pstr=NULL;
strcpy(pstr,"hello world!");
cout<<pstr<<endl;
system("pause");
return 1;
}
运行程序将出现:
3. 引用指向已删除(delete或free)内存的指针(此时指针所指向的内存是释放后的内存,不可读写)
例如:
int main(){
char* pstr=new char[13];
delete []pstr;
strcpy(pstr,"hello world!");
cout<<pstr<<endl;
system("pause");
return 1;
}
运行程序将出现:
4. 引用指向子函数局部变量的指针(此时指针所指向的内存是释放后的内存,可写入但读乱码)
例如:
char* test(){
char str[13];
return str;
}
int main(){
char* pstr=test();
strcpy(pstr,"hello world!");
cout<<pstr<<endl;
system("pause");
return 1;
}
程序可运行,但输出字符串pstr将出现乱码:
5. 引用指向常量的指针 写入位置出错(此时指针所指向的内存是常量区内存,可读不可写)
例如:
int main(){
char* pstr="12345";
strcpy(pstr,"hello world!");
cout<<pstr<<endl;
system("pause");
return 1;
}
运行程序将出现:
6. 引用指向栈区数组的指针(操作中通过指针访问了越界的内存)
例如:
int main(){
char str[12];
char* pstr=str;
strcpy(pstr,"hello world!");
cout<<pstr<<endl;
system("pause");
return 1;
}
运行程序将出现:
7. 引用指向堆区数组的指针(操作中通过指针访问了越界的内存)
例如:
int main(){
char* pstr=new char[12];
strcpy(pstr,"hello world!");
cout<<pstr<<endl;
delete []pstr;
system("pause");
return 1;
}
运行程序将出现:
总结:上述问题虽然都是小问题,但涉及到通过指针跨函数使用内存(即主调函数调用了以指针作为参数或者以指针作为返回值的函数)时,容易出现错误。前面程序实例中调用strcpy()和test()函数出错就是这么一种简单的情况,当函数调用关系更加复杂的时候,上述问题就需要引起足够的重视。