您的位置:首页 > 编程语言 > C语言/C++

c++:strcat潜在的错误不报告

2012-03-13 22:04 232 查看
#include<iostream>

#include<cstring>

using namespace std;

int main()

{

char a[]="hello";

char b[]="world";

cout<<strlen(a)<<endl;

strcat(a,b);

cout<<a<<endl;

cout<<strlen(a)<<endl;

}

运行结果:

5

helloworld

10

这个小程序中数组a的大小被改变了,但是可以正常运行。潜在的错误影响呢????

分析如下:http://blog.csdn.net/sendfeng/article/details/6215016。感谢sendfeng.

首先,这是一个非常有趣的问题!

我也是最近看了一本《C++高效编程:内存与性能优化》的书才弄明白其中的奥秘!

我们先来看一个“奇怪”的现象:

CODE:
struct A { char a; long b; char c; long d; };

        struct B { char a; char c; long b; long d; };

        cout << sizeof(A) <<endl;

        cout << sizeof(B) <<endl;
按照常理,输出都应该是 10 ,其实实际运行结果是16,12 !是不是很奇怪???

为什么会出现这个现象呢?因为编译器会强制char类型的变量与long类型的变量在内存中对齐!

举例看结构A在内存中的布局如下:

地址 内 容

00 字符a

01 未用

02 未用

03 未用

04 long b, byte 0

05 long b, byte 1

06 long b, byte 2

07 long b, byte 3

08 字符c

09 未用

......

可以看到其中的原因了吧!

再看看LZ的程序的原因。

C++的系统函数strcat()的功能只是简单的拼接字符串,自身没有检测是否越界的功能!所以,当拼接后的新的字符串长度大于原始的空间时,strcat()会修改邻接的内存空间!所调用strlen()所取得的长度是截止到 '/0' 的长度!但是调用sizeof()会发现其空间大小还是10!

按照上面的说法,字符数组a后面的空间应该被修改,所以b的内容会变化,但是C++编译器分配内存空间是按照倒栈的顺序的,如果把b放到a前面定义,才有可能被修改!但是由于开始说的内存对齐问题的存在,因此字符数组b的内容还是没有被改变。

大家可以看看下面的程序,分别输出a,b的地址。

CODE:
int main(){

    char b[10] = "good";

    char a[10] = "java is";

    strcat(a," ");

    strcat(a,b); 

    cout << int(&b) << endl;

    cout << int(&a) << endl;

    return 0;

}
运行结果为:

2293600

2293584


(该运行结果取决于不同的机器与编译器,但是反映的问题还是很明显的!)

a,b的头地址相距16Byte,而a的默认空间只有10Byte,还有6Byte的空间是什么呢?

当执行strcat()时,越界的部分就覆盖了这6Byte的内容,但是还没有影响到b的内容,为了证明strcat()确实存在越界的问题,我们可以构造一个特例,程序如下:

CODE:
int main(){

    char b[30] = "good, but i don't think so!";

    char a[10] = "Java is";

    strcat(a," ");

    strcat(a,b);

    cout<<a<<endl;

    cout<<b<<endl; 

    cout << int(&b) << endl;

    cout << int(&a) << endl;

    return 0;

}
我们把b放得足够大,然后调用strcat(),使得拼接后的字符串的长度大于16,这样的话,不仅仅是a,b之间的6Byte被覆盖,b的内容也被覆盖了!

程序运行结果如下:

Java is good, but i don't think so!

t i'dont think so!



可以看到,越界是存在的!

最后总结一下:

strcat()存在越界的问题,因此我们在使用该函数之前需要确保目标字符数组的空间足够大!在原始的程序中,由于变量较少,运行似乎没错,但是还是有很严重的BUG的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: