根据所学,除了结束字符外,所定义b[9]应该能放9个字符啊?在VS.net2003中实现代码如下:
char b[9];
char *s=&b[0];
strcpy(s,"12345678");//超过8个字符要溢出(不解啊)
char *ss=new char[9];
strcpy(ss,"123456789");//可以用到9个字符
char b[9];
char *s=&b[0];
strcpy(s,"12345678");//超过8个字符要溢出(不解啊)
char *ss=new char[9];
strcpy(ss,"123456789");//可以用到9个字符
char b[9];
空间分配在程序栈上,任何的超过其长度的操作都会引起异常而char *ss=new char[9];空间分配在堆上
如果指针超出分配的长度,不一定会有异常的。
第二种方法ss动态申请一块内存空间,并指向该内存空间,该内存空间用来存放9个字符;
所以实际要占10 bytes所以应该不会溢出
eok () 为什么说它溢出???
最后一个字符必须是ASCII码为零的字符
也就是'\0'char b[9];
char *s=&b[0];
strcpy(s,"12345678");//超过8个字符要溢出(不解啊)为什么只能存放八个字符呢?
因为最后一个,也就是b[9]存放了'\0'char *ss=new char[9];
strcpy(ss,"123456789");//可以用到9个字符你可以试着printf("%s", ss);
你就知道为什么了换句话说编译器看ss, b的角度是不一样的
一个是字符串,而另一个是字符数组
因为字符串自动要以0结束,
因此都最多能放8个字符。
多放了都会溢出!!!就是说, 第二种也是错误的!
只是这个错误还没有表现出来而已。
当new char[9];后面有其它的数据时,
错误才可能休现出来, 而且有各种可能的表现形式。
这种错误是最难定位和查找的, 因此要极力避免。
因为字符串自动要以0结束,
因此都最多能放8个字符。
多放了都会溢出!!!就是说, 第二种也是错误的!
只是这个错误还没有表现出来而已。
当new char[9];后面有其它的数据时,
错误才可能休现出来, 而且有各种可能的表现形式。
这种错误是最难定位和查找的, 因此要极力避免。
printf("%s",ss);
你就会明白什么叫出错了b[9]应该能放9个字符啊,没有错,如果放字符串的话只能是8个字符组成的字符串
最后一个'\0'也是一个字符,是特别字符 字符串结束符
char b[9];
char *s=&b[0];
strcpy(s,"123456789");//超过8个字符要溢出(不解啊)
char *ss=new char[9];
strcpy(ss,"123456789");//可以用到9个字符char ch1 = s[9];
char ch2 = ss[9];经过调试ch1,ch2都为'\0'(ascll码)
楼主也试试吧
不代表没有错
s[9],ss[9]不属于s
有可能s[9],ss[9]被修改
(可能被分配给别的变量)
如果'\0'被修改成其它的
就有问题了.
假如:
内存ss如下:
12345689'\0'XXXXXXXXXxxx'0'
如果'\0'被改成字符1.
那么ss就变成了:
123456891XXXXXXXXXxxx
应该是堆栈的问题
char b[9]毫无疑问,可以放9个字节的东西
但是怎么放,怎么取是问题
c语言处理字符有其特殊约定
在栈中有边界问题
但是在堆中,越界会发生意想不到的错误
事实上,在数组中,连续定义的字符缓冲区也可能overlap,但不会提示任何错误
vc2003在测试:
char b[9];
char *s=&b[0];
strcpy(s,"123456789");//超过8个字符要溢出(不解啊)
char *ss=new char[9];
strcpy(ss,"123456789");//可以用到9个字符char ch1 = s[9];
char ch2 = ss[9];经过断点调试ch1和ch2都为0(ascll码),也就是说不存在溢出
但是接着运行下去
Run-Time Check Failure #2 - Stack around the variable 'b' was corrupted.
翻译过来就是“运行时检查错误#2-变量b堆栈异常”
所以说,我的主题也许要改成为什么ss不会堆栈异常了。
你的ss分配在heap上,不是stack上。“Run-Time Check Failure #2 - Stack around the variable 'b' was corrupted.”正说明你在9个长度的栈空间上,要覆盖上去10个字符(包括了一个null)
……而栈被重写可能会造成严重的问题,因此运行环境报告了这个异常。对于ss,你分配了9个长度的堆空间上,你覆盖上去10个字符(包括了一个null),没有
报错,不等于没有错!!!
例如,假设你的代码new了一个空间A,长度为8,操作系统可能给你的地址是1000
假如你再new了一个空间B,长度为8,那么操作系统可能给你的地址是1008现在你要对A空间strcpy一个9字节长(包括了null)的串,那么实际上这个串将
占据1000~1008的空间,也就是说,你的B中的数据被破坏了!
那么再这个情况下可能不会异常,只是你的运行结果不一定是你想要的东西了假设B不是你分配的空间,而是你的运行程序的函数库或者操作系统自动new出来的
那么,如果你破坏了B,就有可能异常。前边有dx说的非常清楚,没有报告异常不等于没有错误!
哎,哪位把strcpy的实现和程序栈和堆的概念讲给楼主吧
using namespace std;
int main()
{char b[9];
char *s=b;
strcpy(s,"123456789");
char *ss=new char[9];
strcpy(ss,"123456789");char ch1 = s[9];
char ch2 = ss[9];
printf("%s",s);
cin.ignore();
}
输出“123456789”
得到结果是在win32控制台下的编程下不会有出错,但在MFC和API编程环境下就有
Run-Time Check Failure #2 - Stack around the variable 'b' was corrupted.
报错,对于strcpy的实现和程序栈和堆的概念我真的一无所知,所以还烦请zzyx(菜农)
说说!win32控制台下没有报异常,是否仍然不该这样分配?
#include "string.h"void main()
{
char b[9];
char *s=b;
strcpy(s,"123456789");
char *ss=new char[9];
strcpy(ss,"123456789");//可以用到9个字符
printf("%s\n%s\n",s,ss);
}
两种方式没有什么本质区别,
因为字符串自动要以0结束,
因此都最多能放8个字符。
多放了都会溢出!!!就是说, 第二种也是错误的!
只是这个错误还没有表现出来而已。
当new char[9];后面有其它的数据时,
错误才可能休现出来, 而且有各种可能的表现形式。
这种错误是最难定位和查找的, 因此要极力避免。而且,空间分配在程序栈上,任何的超过其长度的操作都会引起异常
而char *ss=new char[9];空间分配在堆上
如果指针超出分配的长度,不一定会有异常的。
如果小余9个,则最后会自动加'\0'。
#include "stdio.h"
#include "string.h"void main()
{
char b[9];
char *s=b;
strcpy(s,"123456789");//超过8个字符要溢出(不解啊)
char *ss=new char[9];
strcpy(ss,"123456789");//可以用到9个字符
printf("%s\n%s\n",s,ss);
char ch1,ch2;
for(int i=0;i<9;i++)
{
ch1=s[i];
ch2=ss[i];
}
}
strcpy不检查溢出,摘自MSDN
The strcpy function copies strSource, including the terminating null character, to the location specified by strDestination. No overflow checking is performed when strings are copied or appended
char a[5];//定义了5个整数,分别是a[0] a[1] a[2] a[3] a[4]
那么a[5]呢,根本不存在,a[4]要放结束符,所以只能放4个字符,不明这个才是我真正的错误,后面请大家看明白了再跟贴:
VC.net2003
在Win32控制台编程(类似于DOS界面的编程)测试
#include <iostream>
using namespace std;
int main()
{char b[9];
char *s=b;
strcpy(s,"12345678超过");//超过8个字符要溢出(不解啊)
char *ss=new char[9];
strcpy(ss,"了原定义大小12345678");//可以用到9个字符
printf("%s",b);
printf("%s",s);
printf("%s",ss);
cin.ignore();
delete[]ss;
}
所得到结果输出"12345678超过12345678超过了原定义大小12345678"
也就是说在win32控制台下的处理异常宽容。在MFC和API编程环境下则会报错
Run-Time Check Failure #2 - Stack around the variable 'b' was corrupted.所以说,我的主题不是改成为什么ss不会堆异常了,而是数组要这么个理解了。我的另一个问题还没有人解答,请有能力的朋友不妨看看http://expert.csdn.net/Expert/topic/2162/2162022.xml?temp=.9801142