KeyFansClub

首页 » - 特色讨论区 - » 键社茶餐厅 » C++啊~~我的青春啊~~我哭,达人来帮忙看看吧!
蓝空公主 - 2006/5/15 2:34:00
花半个月写的代码,在今天调试的时候发生重大问题
闻所未闻、见所未见的问题
C++真是诡异
某半个月的努力完全XD了

达人们一起来想想到底是什么问题
程序已经通过编译器语法检查
我写的基类(已经通过了调试)中包含一系列的宏
#define NONIUS_NEXT        (PosNonius++,Nonius->next)
#define NONIUS_PREV        (PosNonius--,Nonius->prev)
#define NONIUS_HEAD        (PosNonius = 0,head)
#define NONIUS_FOOT        (PosNonius = Lenlist,foot)
#define NONIUS_NULL        (PosNonius = 0,NULL)

Nonius是链表中的游标
PosNonius记录Nonius当前所在链表中的位置
靠上面的宏就可以保证游标Nonius和PosNonius同步工作
我从一开始写程序就保证只有glideNonius(ulong position)函数可以操作该游标
ulong是usigned long的别名
以上成员均被封装于类TLK的private
public区有成员ulong LKgetValue(ulong position)函数
ulong TLK::LKgetValue(ulong position)
{
    glideNonius(position);
    return Nonius->value;
}

TLK的所有工作已经调试无误

之后TLK被类TTR以private形式继承
TTR中有public函数ulong TRgetChild(ulong ramusPos)
ulong TTR::TRgetChild(ulong ramusPos)
{
    return LKgetValue(ramusPos);
}
在执行此函数时发生这样的错误:
PosNonius的数值总是和ramusPos相同
Nonius也有同样的位移(等效于执行ramusPos次NONIUS_NEXT)

这也就罢了
当ramusPos > 1时
TRgetChild函数返回后发生更为诡异的事:
PosNonius此时居然自动变成1
Nonius则跑到head上(即PosNonius为0时Nonius应该在的位置)
完全打破了两者的同步

尝试把形参名ramusPos改为ramusPs 之后
TRgetChild函数执行时
不再发生PosNonius的数值总是和ramusPs相同的情况
但是Nonius依然异常
函数返回后PosNonius还是自动变为1
Nonius还是自动回到了head上


顺便说一句在step模式下发生这些异常时并没有发现程序执行额外的代码
问题总是发生在调用和返回的时候

经过跟踪变量和step执行
目前排除以下情况:
1.成员覆盖
2.错误的代码操作


目前怀疑:
1.编译问题
2.某些特殊的继承规则
3.溢出
4.RPWT (这个最汗 —v—b)
LOVEHINA-AVC - 2006/5/15 4:09:00
看来LZ需要学会使用OLLYDBG……或者2K5也可以在ASM模式下调试XD
kuangallan - 2006/5/15 6:56:00
以下引用LOVEHINA-AVC在2006-5-15 4:09:17的发言:
看来LZ需要学会使用OLLYDBG……或者2K5也可以在ASM模式下调试XD


-v- avc 样,你以为随便一个人都能像你那计算机一样强大的过程化脑袋啊。你直接帮忙看源代码哪个字母大小写写错都好过你叫人家学软件调试啦。
LOVEHINA-AVC - 2006/5/15 7:03:00
哪有这么夸张……编译发现不了问题当然就得用汇编级调试啊-口-|||
Prz - 2006/5/15 11:58:00
编译器一般情况下肯定是正确的,这个基本可以不用怀疑。

这种问题一般是写程序的时候逻辑混乱造成的。
把代码列出来看看就可知。
Prz - 2006/5/15 12:08:00
以下引用LOVEHINA-AVC在2006-5-15 7:03:17的发言:
哪有这么夸张……编译发现不了问题当然就得用汇编级调试啊-口-|||


经过优化后的汇编不是人类可读的....

不过如果我推测得不错的话,估计VC里面的Debug可以显示CPU窗口,可以进行汇编级别的步进;
Linux下GDB可以用Stepi模式;

不过链表程序的最佳Debug工具是DDD, D起来简直是享受啊 -v-|||
zhangxiushen - 2006/5/15 12:29:00
这里有高手呀...................
还好我学的不是C++..............
这里是GalGame论坛的说..........
LOVEHINA-AVC - 2006/5/15 12:36:00
看楼上的签名就知道跟MISHA一样都是用DELPHI的
zhangmdk - 2006/5/15 12:41:00
楼上今后的进化目标就是UE打开一个EXE或者DLL马上就能在脑中转化为运行过程兼数据……

编程苦手路过……
watashia - 2006/5/15 12:47:00
以下引用zhangxiushen在2006-5-15 12:29:48的发言:
这里是GalGame论坛的说..........


不对哦,这里不是GALGAME论坛 -v-||
这里有时候是程序员论坛,有时候是物理论坛,有时候是考古论坛,有时候是八卦论坛,有时候是……

看你上论坛时的RP了 =v=++
LOVEHINA-AVC - 2006/5/15 12:52:00
以下引用zhangmdk在2006-5-15 12:41:50的发言:
楼上今后的进化目标就是UE打开一个EXE或者DLL马上就能在脑中转化为运行过程兼数据……

编程苦手路过……


我是BOT吗……
PS:来战EFZ哇
zhangmdk - 2006/5/15 13:04:00
明天就答辩了……今天玩好好准备一下明天好强暴老师们……
LOVEHINA-AVC - 2006/5/15 13:10:00
要准备喷老师一脸口水了么
勇敢的MDK啊快去创造奇迹……
粘土火星 - 2006/5/15 13:12:00
才不是GalGame论坛=3=

这里应该是KF的活动场所,我们的KF有时候是程序员,有时候是物理学家,有时候喜欢考古,有时候-v-bbbbbb

PS:虽然在下不懂C++……不过楼主的贴很难读………………
LOVEHINA-AVC - 2006/5/15 13:13:00
以下引用粘土火星在2006-5-15 13:12:49的发言:
PS:虽然在下不懂C++……不过楼主的贴很难读………………


此句貌似不构成转折关系=v=ddd
watashia - 2006/5/15 13:15:00
啊!!
彻底成水帖了 XD
另外xixi的回帖有抄袭的嫌疑啊 XD
粘土火星 - 2006/5/15 13:18:00
以下引用LOVEHINA-AVC在2006-5-15 13:13:44的发言:

此句貌似不构成转折关系=v=ddd


言下之意就素那个代码风格有点寒

至于抄袭,可以当作重载……

话说C++的问题找Tai来=v=
kkkklll - 2006/5/15 14:23:00
调程序本来就是一件很orz的事情呀,楼主多加几堆 Assert,多跟踪几次吧。

C++ 都快忘光了……用惯了C#,最近要我做C++ 的程序觉得巨郁闷……
蓝空公主 - 2006/5/15 15:36:00
目前确实也找不到程序到底逻辑上有什么问题
估计前期策划不好到后期就这样了
即便有问题Debug也很难找
本人根本不懂win32汇编 —v—

看来是不能在上面继续拖时间了
现在我决定重写这一部分的代码
幸好只是两个星期的工作量

谢谢大家提供意见!!
zhangxiushen - 2006/5/15 16:05:00
刚刚的楼下LOVEHINA-AVC好厉害......知道我用Delphi.
但是我也用c#和原生c++和 object-pascal的说.
拒绝mfc.....
LOVEHINA-AVC - 2006/5/15 16:40:00
<-此人对C++过敏,ASM倒是最常用的
orlye - 2006/5/15 17:18:00
以下引用zhangxiushen在2006-5-15 16:05:07的发言:
刚刚的楼下LOVEHINA-AVC好厉害......知道我用Delphi.
但是我也用c#和原生c++和 object-pascal的说.
拒绝mfc.....

弱弱地问一下,为什么拒绝MFC啊?
skypaul - 2006/5/15 17:24:00
c++么..
某乐仅学到C的初级...
遥远啊-(远目)
PS:某乐今年初一
粘土火星 - 2006/5/15 17:28:00
说到Delphi……现在这东西有新东家了吗

TO 楼主:

在执行此函数时发生这样的错误:
PosNonius的数值总是和ramusPos相同


这个问题貌似是正常的程序逻辑=  =bbb
glideNonius是怎样实现的????
wdx04 - 2006/5/15 19:18:00
不知道楼主想做什么。
这是我猜楼主的意思:

#include "stdafx.h"

#define NONIUS_NEXT  (PosNonius++,Nonius->next)
#define NONIUS_PREV  (PosNonius--,Nonius->prev)
#define NONIUS_HEAD  (PosNonius = 0,head)
#define NONIUS_FOOT  (PosNonius = Lenlist,foot)
#define NONIUS_NULL  (PosNonius = 0,NULL)

typedef unsigned long ulong;

struct Node
{
    ulong value;
    Node *next,*prev;
}*head,*foot;

class TLK
{
private:
    Node *Nonius;
    ulong PosNonius;

    void glideNonius(ulong position)
    {
        if(position>PosNonius)
        {
            while(position>PosNonius)
                Nonius=NONIUS_NEXT;
        }
        else if(PosNonius>position)
        {
            while(PosNonius>position)
                Nonius=NONIUS_PREV;
        }
    }

public:
    TLK()
    {
        Nonius=head;
        PosNonius=0;
    }

    ulong LKgetValue(ulong position)
    {
        glideNonius(position);
        return Nonius->value;
    }

    void Print() const
    {
        printf("PosNonius=%d\n",PosNonius);
    }

    void IsNoniusEquals(Node *pnode) const
    {
        if(pnode==Nonius)
            printf("Yes\n");
        else
            printf("No\n");
    }

};

class TTR : private TLK
{
public:
    TTR()
    {
    }

    ulong TRgetChild(ulong ramusPos)
    {
        return LKgetValue(ramusPos);
    }

    void Print() const
    {
        TLK::Print();
    }

    void IsNoniusEquals(Node *pnode) const
    {
        TLK::IsNoniusEquals(pnode);
    }

};

int main(int argc, char* argv[])
{
    Node testNodes[10];
    head=testNodes;
    foot=testNodes+9;
    for(int i=0;i<9;i++)
    {
        testNodes.next=testNodes+i+1;
        testNodes[i+1].prev=testNodes+i;
        testNodes.value=i;
    }
    testNodes[9].value=9;
    TTR ttr;
    printf("%d\n",ttr.TRgetChild(3));
    ttr.Print();
    ttr.IsNoniusEquals(testNodes+3);
    return 0;
}

执行结果是:
3
PosNonius=3
Yes
没有错误。
Rinrin - 2006/5/16 11:16:00
没看明白楼主的意思.....
kkkklll - 2006/5/16 12:19:00
以下引用orlye在2006-5-15 17:18:56的发言:

弱弱地问一下,为什么拒绝MFC啊?


我在 M$ 没见到任何人用过 MFC... 要么 C++ 要么 C# ,也有些人用VB 或 Script。

呵呵。至于我已经完全以C#为最优先了。
LOVEHINA-AVC - 2006/5/16 14:29:00
楼上在M$里工作吗?
Rinrin - 2006/5/16 14:59:00
不会吧
至少Spy++是用MFC写的....
kkkklll - 2006/5/16 15:21:00
我的IP呀……而且Proxy设置不能……想用个马甲都不行……

我不是M$员工,只是外包来M$做测试的,或许是做测试级比较低所以见得不全。但是我的确没见到还有人用MFC的了,Dev那边也只是用C++加API,或VC++.Net。几年前的程序当然很多用的啦。

C#用的人比较多,毕竟M$主推这个瓜瓜,VS2005的C# IDE功能也相当强大。呵呵,又给M$作广告了。