[C++]指针被莫名其妙修改了……

2013-09-29 22:05:11 +08:00
 KickTR
先别急着吐槽下面这段代码有多烂_(:з」∠)_(因为老师教的时候就有问题我还傻愣愣地按照老师的那套思路去做)
在学校机房的VC++6上调试会有问题,自己的Ubuntu上eclipse调试也是同样的问题:指针被莫名其妙修改了。

主要就是输入数字模拟抽取手牌的过程,手上如果有相同的牌就把手上的牌扔掉,没有的话就按从小到大排序好。

#include <iostream>
#include <malloc.h>
using namespace std;

typedef struct card
{
int data;
struct card *next;
} aCard, *list;
——————下面可以忽略(应该没问题吧?)——————
int insertc(list handcard)
{
aCard inputcard;
list p;
cin>>inputcard.data;
inputcard.next=NULL;
p=handcard;
//check first card
if (handcard->next==NULL)
{
cout<<"1st card"<<endl;
handcard->next=&inputcard;
return 0;
}
while(p->next->data<inputcard.data && p->next!=NULL)
{
p=p->next;
}

//add card at the end
if (p->next->next==NULL)
{
p->next->next=handcard;
return 0;
}

//delete card;
if (p->next->data==inputcard.data)
{
list q;
q=p->next;
p->next=p->next->next;
free(q);
cout<<"free a card"<<endl;
return 0;
}

//insertcard
if (p->next->data<inputcard.data)
{
inputcard.next=p->next->next;
p->next->next=&inputcard;
}
return 0;
}

list createlist()
{
list Clist;
Clist=(card*)malloc(sizeof(card));
Clist->data=0;
Clist->next=NULL;
return Clist;
}
——————上面可以忽略——————
int main()
{
list handcard,p;
handcard=createlist();
p=handcard;
for (int i=0;i<5;i++)
{
insertc(handcard);
while (p->next)
{
//重点在这里
//一旦执行了下面任何一句话都会使得后一句指针p的指向内容以及next被修改掉,使得p=p->next这句毫无意义并且废掉了p
//本意是为了抓取一次新牌后就打印一次手里的所有牌,结果发现指针莫名其妙被修改
//因为*p和*handcard指向相同空间所以handcard里面的内容也会被改掉
//————问题代码——————
//printf("1234");
//cout<<p->data<<" "<<endl;
//cout<<"anything"<<endl;
//————(end)————
p=p->next; //单独执行这句就不会有问题,不过一旦while结束后继续执行后面的代码指针p指向内容也会瞬间乱掉
}
cout<<endl;
}
return 0;
}

为什么随便打印点东西都会让p指向混乱呢?试着单步跟每次都是跟到while开始下一句执行时p就乱了。
另外,其实main函数是有点问题的还没完全调试好,不能正确连续打印手牌,不过和上面所述问题无关,我只想知道为什么执行一下输出都会扰乱指针p的内容
相当纠结,本人水平很弱,特此处女贴来求助……
4746 次点击
所在节点    程序员
21 条回复
SErHo
2013-09-29 22:19:39 +08:00
你的代码中createlist 返回的到底是个什么东西?编译时不会报错,警告吗?
SErHo
2013-09-29 22:26:32 +08:00
@SErHo 哦,对不起,看错了。
zorceta
2013-09-29 22:36:01 +08:00
C++为嘛不上new/delete
pomelowu
2013-09-29 22:38:13 +08:00
aCard inputcard;
是局部變量。
SErHo
2013-09-29 22:38:37 +08:00
主要就是插入节点的时候用的是局部变量inputcard,你应该使用malloc。
raptium
2013-09-29 22:39:13 +08:00
你为你 createlist 返回的东西在 stack 里
不在 heap 里
raptium
2013-09-29 22:39:25 +08:00
因为*
leunggamciu
2013-09-29 22:39:31 +08:00
上GDB,上单步,当你最终发现问题的时候你会有一种豁然开朗和想一刀捅死自己的感觉!
raptium
2013-09-29 22:42:47 +08:00
哦 说错了 不是 createlist,是 insertcard 里插入的东西
嗯 都是一个意思= =
pathletboy
2013-09-29 22:45:21 +08:00
int insertc(list handcard)
{
aCard inputcard;
list p;
cin>>inputcard.data;
inputcard.next=NULL;
p=handcard;
//check first card
if (handcard->next==NULL)
{
cout<<"1st card"<<endl;
handcard->next=&inputcard;
return 0;
}

妥妥的有问题 ,你inputcard是局部变量。
frogs
2013-09-29 23:05:19 +08:00
gcc -S
xdeng
2013-09-30 00:24:28 +08:00
查查字节对齐 这也是一个很坑爹的问题
lukic
2013-09-30 08:55:34 +08:00
@raptium
@pathletboy
正解。
helayzhang
2013-09-30 08:57:53 +08:00
9L正解
chchwy
2013-09-30 09:30:15 +08:00
http://www.v2ex.com/t/74249 [V2EX技巧] 贴图和贴代码的方法
KickTR
2013-09-30 15:53:24 +08:00
@SErHo @raptium @pathletboy @pomelowu @lukic @helayzhang 感谢各位的相助,的确是局部变量问题,new之后就没事了。
这段代码其实还有诸多小错误,现在都已经差不多修正好了。

@zorceta 因为老师上课时是用VC演示,使用的cpp,但是代码正文却混合了c和c++极其不规范,还采用h头文件,他是用的malloc,当时我还不太了解,后来查了之后才知道c++中应该使用new不再需要malloc。这个老师的编程习惯也很不好,经常没有对齐的,哎。

@chchwy thx~

感谢各位相助。不过我还是有一点不太明白,在单步跟踪时,既然inputcard是局部变量,完成了插入节点函数之后为什么对应inputcard的连在链表上的数据没有被立即销毁(变量监视中看到的)?而且可以继续在主函数里单独执行p=p->next,变量监视中也能显示正确连上去
pathletboy
2013-09-30 16:06:17 +08:00
@KickTR 内存销毁不是你想象的不可访问,只是在编译器中标记了这段内存无主了,其他人可以使用,局部变量是在堆栈中的,堆栈是编译器为线程申请的一块内存,一般为2M,由ebp/esp寄存器控制进行访问,在同个线程中,堆栈是给该线程调用的所有函数复用的。
KickTR
2013-09-30 16:21:55 +08:00
@pathletboy 谢谢,意思是不是说,局部变量在所在函数结束后,变量对应空间的内容没有被立即清零,只是变量对应空间被标注可用,所以空间里存储的数据可能仍然存在,但是内容所处空间会随时可能被任何其他函数调用导致内容被修改?
pathletboy
2013-09-30 16:26:36 +08:00
@KickTR 嗯,是这样,如果没有其他函数对你那块堆栈值修改,那块内存你就可以一直使用,这有点像一块公共区域,你放置了一个东西,在其他人没搬走丢弃你的东西之前,你一直可以使用。
KickTR
2013-09-30 16:36:56 +08:00
@pathletboy 十分感谢!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/84183

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX