关于cout实在是很郁闷,高手帮小弟解决一下。
小弟今日在解决网友问题时写了一段程序,程序的作用是提取一字符串里合理的邮箱地址。最后的时候问题出来了,在用cout < <的时候发现出现错误。请先看下面代码
#include <iostream>
#include <string.h>
using namespace std;
char *charCopy(int a,int b,char *p);
char **findMail(char a[])
{
int len;
int count=0;
int count2=0;
int count3=0;
len=strlen(a);
int Flag=0;
char *t[10];
for (int i=0;i <10;i++)
{
t[i]=new char[40];
t[i]=a;
}
while(count <len)
{
while(count <len)
{
if( '@ '==a[count])
{count2=count;count3=count;count++;break;}
count++;
}
if (count> =len)
break;
while(*a)
{
if((a[count2]> = '0 ' && a[count2] <= '9 ')||( a[count2]> = '@ ' && a[count2] <= 'Z ')||( a[count2]> = 'a ' &&a[count2] <= 'z ')||(a[count2]== '_ ')||(a[count2]== '. '))
{count2++;}
else
break;
}
while(count3> =0)
{
if((a[count3]> = '0 ' && a[count3] <= '9 ')||( a[count3]> = '@ ' && a[count3] <= 'Z ')||( a[count3]> = 'a ' &&a[count3] <= 'z ')||(a[count3]== '_ ')||(a[count3]== '. '))
{count3--;}
else
break;
}
t[Flag]=charCopy(count3+1,count2-1,a);//因为count3也读取了‘@ ',所以要加一。
Flag++;
}
return t;
}
char *charCopy(int a,int b,char *p)
{
int Flag=0;
char *t=new char[b-a+1];
while(Flag <b-a+1)
{
*(t+Flag)=*(p+a+Flag);
Flag++;
}
return t;
}
int main()
{
char kk[]={ "++gaozhenyu@sina.com++eggqq007@163.com "};
char **bb=findMail(kk);
for(int i=0;i <10;i++)
cout < <*(bb+i) < <endl;//请在这里设置断点调试。
return 0;
}
当调试到上面的cout时候发现原来的*bb在经过cout语句后尽然变成了0xcccccccc。但是没经过cout的时候绝对是正确的啊。昨晚郁闷了一个晚上,今天连书都看不下。怎么cout还会改变参数的值呢?
望各位给我解答一下,要不今晚又睡不着了!谢了。
[解决办法]
其实区别不在于指针数组和指针的指针
主要在于对象的生命周期
指针数组如果不是局部的也可以
比如你可以把char *t[10];改成static char *t[10];这样也可以
关键在于局部对象在stack中,而全局或静态对象以及用new或malloc动态分配的对象在heap中;
前者在局部作用域退出后对象就会被销毁,后者则不会,需要显示的delete或free
如果你的t是局部对象,不管是指针数组还是指针的指针,在函数返回后还引用会引发未定义行为
[解决办法]
终于明白你的意思,野指针吧?其实即使你不cout,任何函数调用都会引起*bb的改变。
学过OS的人都知道,关于内存分配有很多种策略,有一种在这儿用到:懒惰算法(下一次用到才抛弃)。bb所指的单元因为在cout之前没有用到,所以才会造成可以使用的假象,任何函数调用都会导致bb悬空。内存被回收,bb变成野指针。
[解决办法]
野指针,OS中讲过关于内存分配和回收的其中一种策略称为懒惰算法(用到才回收),在cout之前造成可以使用的假象,调用cout后,bb所指内存被回收,bb悬空变为野指针。
PS:其实,不关cout的事,你即使调用一个空函数(函数执行前进行动态存储空间回收),bb也会悬空。
[解决办法]
也就是你需要的是 t 数组中的各个元素
(这些指针元素才是你需要的,它们指向的内容是new获得的)
但是 返回t这个局部数组,数组内容都被释放了...
(就像char t[]= "Hello "; ... return t;这样你觉到能够得到字符串 "Hello " 么)
至于为什么调试时候“可以清楚地看到*bb指向的地址的值是:gaozhenyu@sina.com ,*(bb+1)指向的地址的值是eggqq007@163.com”,原因两点:
1 所谓的释放,不是说抹去这段内存中的内容,而是告诉系统,这个段内存我不用了,你可以分配给其他进程,在下次操作之前这些内容是不变的。所以,可能return t之后,t数组释放,但是没有被改写数据(没有其他进程占用过这段内存),那么内容不变,自然可以得到原来的内容;
2 和调试环境有关