一个关于指针的错误,十分困惑

一个关于指针的错误,十分困惑

不乱于心 发布于 2021-11-26 字数 3159 浏览 814 回复 9

这是问题函数的代码:

static int m_Simulate(phase& sim_board, int own, POINT last_point)
{
    POINT odds_points[rule::PiecesNums()];
    int round = own;
    while (true)
    {
        LINKTYPES lts;
        sim_board.CheckLinkTypes(round, last_point, lts);
        if (rule::IsBanMove(last_point, lts))
        {
            if (own == PIECES::WHITE) {return 1;}
            break;
        }
        else if (rule::IsOver(lts))
        {
            if (own == round) {return 1;}
            break;
        }

        round = ~round;

        int odds_point_nums = ai::GetKeyPoints(sim_board, round, odds_points);
        if (odds_point_nums < 1)
        {
            break;
        }
        int odds = randomx::Get(odds_point_nums-1);
        last_point = odds_points[odds]; // 此处出现段错误信号

        sim_board.SetPieces(round, last_point);
    }
    return 0;
}

问题的症状,就是当这个函数运行了一定次数后,在那一行会出现一个错误,由于是多线程的,而这个函数运行在子线程,出现这个错误后没有任何异样,操作系统也不显示错误报告。只有在调试的时候才能知道出现了一个指针错误。

从调试信息可以看到,odds_points莫名其妙的变成了0xe,这显然是某个地方发生了错误,然后系统或者运行库把这个odds_points改成了0xe。但我真的不明白还有哪里能发生错误。这里唯一将odds_points传出去的,也是传值啊,不是引用啊,不可能会出现这种问题:int GetKeyPoints(phase& board, int own, POINT result[]);

我后来觉得,会不会是POINT odds_points[rule::PiecesNums()];这里的问题,用了自动数组的特性,于是我尝试用另一个模块的走法表来作为odds_points,这个走法表的数组是new的。我试了之后,发现确实这个函数中不会有段错误的提示了。

但是,很奇怪的事出现了,竟然会影响到另一个毫不相干的list:

static UCTNODE* m_SelectPlayNode(list<UCTNODE*>& nodes, int n)
{
    for (auto node : nodes)
    {
        if (node->access_nums < 1) // 此处会出现段错误
        {
            return node;
        }
    }
...

为什么会段错误?因为node莫名其妙的变成0x0了!而我仔细的调试发现和这个链表相关的那些函数根本没有任何问题,根源依然是那个m_Simulate函数!(在另外一个函数中,是先调用上面的函数,然后再调用m_Simulate,这两个函数没有任何关系,参数也是完全独立的)

因为当我重新恢复POINT odds_points[rule::PiecesNums()];的形式时,上面的函数就不会出现段错误,node也不会莫名其妙的变成0x0。所以我断定这个段错误的根源就是那个m_Simulate引起的。

我怀疑是某个地方莫名其妙的覆盖了别的地方的数据,导致了各种异常表现。这个问题真的很棘手,我在调试时难以获取足够的信息,如果要我看汇编的指令,我也看不出什么来。

真的很困惑很无奈,到底是为什么导致了odds_points会变成0xe,这个肯定也不是根源,应该是更隐蔽的地方导致了这一系列的问题,odds_points用自动数组,在m_Simulate函数里就会出现段错误,莫明其的变成的0xe,不用自动数组,就会影响到另一个毫不相干的list,匪夷所思。这个0xe估计是一个重要的线索,肯定是系统或者运行库检查到某些问题然后改成0xe以提示错误。

说实说我非常想把这个问题归结于编译器和运行库,但我也知道基本不可能的,是我自己某些地方的代码有错误。但这真的很难知道问题到底在哪。

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

灵芸 2021-12-01 9 楼

GetKeyPoints(sim_board, round, odds_points);

在里面odds_points会不会数据存在new出来的内存里了

伪装你 2021-12-01 8 楼

撸主,依我的经验,非常可能是出现了内存非法覆盖的情况,这个问题的解决过程会让人非常痛苦。。。所谓“三分钟经历人生的大起大落”。

切模块,逐个排除。。。你看到的不都是真相!

也只能帮你到这了- -|||

多情癖 2021-12-01 7 楼

问题不一定在这个函数里,查一下调用这个函数的所有地方(函数)是否覆盖了堆栈环境(通常是不正确的内存操作引起),可用最小精简法来逐个排除.按你的描述,基本就是内存越界覆写错误引起.

自此以后,行同陌路 2021-12-01 6 楼

又调皮了

别再吹冷风 2021-12-01 5 楼

回复
哈实话。c++的设计思维与c的不一样。设计方式自然也有差异。即便是面向对象的设计。

奢望 2021-12-01 4 楼

c,我还帮你看看,c++的不懂。哈。

绝影如岚 2021-11-30 3 楼

更加诡异了。

我把POINT odds_points[rule::PiecesNums()];改成POINT odds_points[225] = {};,这个odds_points倒是不会突然变成0xe了,但是别的地方变成0xe了!

sim_board.SetPieces(round, last_point);这一句,这个sim_board的对象指针变成了0xe!,在SetPieces函数中访问类变量时引发了段错误,因为this变成了0xe!

非常诡异,真的很棘手。到底是什么原因呢,这是为什么呢

噩梦成真你也成魔 2021-11-30 2 楼

这个,信息量有点大哈,比较晚了,没细看问题,可以下个条件断点,变成0xe的时候自动断下,再看看堆栈找问题

冬天旳寂寞 2021-11-30 1 楼

调试时我也想到了,可能还就是int odds_point_nums = ai::GetKeyPoints(sim_board, round, odds_points);的问题,因为以前是用别的函数,在改成用GetKeyPoints函数时问题也就出现了。经过我再三确认,还真的是这里有问题。

但我就完全没有头绪了,因为GetKeyPoints中只是纯粹的写一些数据到result数组中,也没有超出边界的地方。而且最麻烦的是,这个odds_points变成0xe一定会出现,但和运行次数并没有关系,就好像是有一人要跳楼,不知道他会在什么时候跳,但反正他最后一定会跳。

具体是这样的,在另外的一个函数,控制着这个模块的基本流程,循环到指定的次数,每一次都相继调用一些函数,其中就是m_Simulate,而这个odds_points变成0xe的错误,是不定时的,不是固定的每次调用都会出现,也不是固定的某次调用会出现,而是突然在某次调用m_Simulate时的就发生了。所以我感觉很棘手,因为连调试都难。