debugging 如何调试运行时检查失败#2?

ttp71kqs  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(139)

当运行下面的代码来计算随机七张扑克牌中无对子、一对、两对、三条、满堂红和四条的概率时,Visual Studio在最后一行返回警告“Run-Time Check Failure #2 - Stack around the variable 'hand_counts' was corrupted”。但是,程序仍然可以通过点击“继续”输出结果。我已经检查了程序的越界数组访问,但没有发现任何。什么可能导致错误?

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
typedef enum suit
{
    spades,
    hearts,
    diamonds,
    clubs
} suit;
typedef struct card
{
    suit suit;
    short pip;
} card;
void deck_shuffle(card deck[52])
{
    srand(time(NULL));
    for (int i = 0; i < 52; i++)
    {
        const int j = rand() % 52;
        const card temp = deck[i];
        deck[i] = deck[j];
        deck[j] = temp;
    }
}
int possibility(card hand[7])
{
    int pair_type = 0;
    int count = 0;
    for (int i = 0; i < 6; i++)
    {
        for (int j = i + 1; j < 7; j++)
        {
            if (hand[i].pip == hand[j].pip)
            {
                count++;
            }
        }
    }
    // check for no pairs.
    if (count == 0)
    {
        pair_type = 1;
    }
    // check for one pair.
    if (count == 1)
    {
        pair_type = 2;
    }
    // check for two pair.
    if (count == 2)
    {
        pair_type = 3;
    }
    // check for three of a kind.
    if (count == 3)
    {
        pair_type = 4;
    }
    // check for full house.
    int rank1 = 0;
    int rank2 = 0;
    int temp1 = hand[0].pip;
    int temp2;
    int count1 = 0;
    int count2 = 0;
    for (int i = 0; i < 6; i++)
    {
        for (int j = i + 1; j < 7; j++)
        {
            if (hand[i].pip == hand[j].pip)
            {
                rank1 = hand[j].pip;
                if (temp1 == rank1)
                {
                    count1++;
                    temp1 = rank1;
                }
                else
                {
                    temp2 = rank2;
                    rank2 = hand[j].pip;
                    if (temp2 == rank2)
                    {
                        count2++;
                    }
                }
            }
        }
    }
    count2 += 1;
    if ((count1 == 3 && count2 == 1) || (count1 == 3 && count2 == 3))
    {
        pair_type = 5;
    }
    // check for four of a kind.
    if (count1 == 6 || count2 == 6)
    {
        pair_type = 6;
    }
    return pair_type;
}
int main(void)
{
    card deck[52];
    for (int i = 0; i < 52; i++)
    {
        deck[i].suit = i / 13;
        deck[i].pip = i % 13;
    }
    int hand_counts[6] = { 0 };
    for (int i = 0; i < 1000000; i++)
    {
        deck_shuffle(deck);
        card hand[7];
        for (int j = 0; j < 7; j++)
        {
            hand[j] = deck[j];
        }
        int hand_type = possibility(hand);
        hand_counts[hand_type - 1]++;
    }
    for (int i = 0; i < 6; i++)
    {
        printf("The probability of hand type %d: is %f\n", i + 1, (double)hand_counts[i] / 1000000);
    }
    return 0;
}

我尝试在其他IDE中运行相同的代码,没有任何警告。计算结果也比Visual Studio快。我不确定是我的源代码中有错误,还是Visual Studio本身有问题。

h22fl7wq

h22fl7wq1#

对不起,但是possibility()结尾的多个循环和变量有点难以理解。我把它剥离了一些,并放入一个特定的测试用例; 4个aces:

int possibility( int hand[7]) {
    int pair_type = 0;

    /* ... */

    for (int k = 0; k < 7; k++) printf( "%d ", hand[k] );

    int rank1 = 0;
    int rank2 = 0;
    int temp1 = hand[0];
    int temp2;
    int count1 = 0;
    int count2 = 0;
    for (int i = 0; i < 6; i++) {
        for (int j = i + 1; j < 7; j++) {
            if (hand[i] == hand[j]) {
                rank1 = hand[j];
                if (temp1 == rank1) {
                    count1++;
                    temp1 = rank1;
                } else {
                    temp2 = rank2;
                    rank2 = hand[j];
                    if (temp2 == rank2)
                        count2++;
                }
            }
        }
    }

    count2 += 1;
    printf( "\nSuspicion: count1 = %d count2 = %d\n", count1, count2 );
    /* ... */
    return pair_type;
}

int main(void) {
    int hand[7] = { 12, 0, 0, 0, 0, 1, 2 };

    printf("hand type %d\n", possibility(hand) );

    return 0;
}

测试结果:

12 0 0 0 0 1 2
Suspicion: count1 = 0 count2 = 7   // <<<<
hand type 0

然后又道:

int hand_type = possibility(hand);
        hand_counts[hand_type - 1]++;

将增加位置hand_counts[ 0 - 1 ].
你需要回到嵌套的for()循环,找出如何避免 * 重复计数 。4-of-a-kind可以在任何位置出现。在你的循环中有太多的 * 重复计数
建议你看看“直方图”计数的卡(int cnt[13] = {0};将是一个开始。然后一个单一的通过手将给你给予你需要的计数。
或者是Visual Studio本身的问题。
”虽然这总是一种可能性,但一个可怜的工匠会开始责怪他/她的工具。
你知道..

int hand_counts[ 27 ] = { 0 }; // why not?
/* ... */
    for (int i = 0; i < sizeof hand_counts/sizeof hand_counts[0]; i++)
    {
        printf("The probability of hand type %d: is %f\n", i, (double)hand_counts[i] / 1000000);
    }

(Just注意到你在打印语句中“加1”了!太多的“聪明”溢出变成了“愚蠢”.)

加班:

有趣的是,这里有一个精简的版本,可能适合详细说明更大的东西:

void deck_shuffle( int deck[] ) {
    for( int i = 0; i < 52; i++ ) {
        const int j = rand() % 52;
        const int temp = deck[i];
        deck[i] = deck[j];
        deck[j] = temp;
    }
}

int cmp( const void *a, const void *b ) {
    return *(int*)b - *(int*)a; // descending sqnc
}

enum { nada, four, three, two, twoPair, fullhouse, nTallies };

int possibility( int hand[] ) {
    int cnt[13] = { 0 };

    for( int i = 0; i < 7; i++ ) {
        printf( "%c ", "A234567890JQK"[ hand[i] ] );
        ++cnt[ hand[i] ];
    }

//  qsort( cnt, sizeof cnt[0], 13, cmp ); // Wrong!
    qsort( cnt, 13, sizeof cnt[0], cmp ); // descending

    if( cnt[0] == 4 ) return four;

    if( cnt[0] == 3 )
        if( cnt[1] == 2 )
            return fullhouse;
        else
            return three;

    if( cnt[0] == 2 )
        if( cnt[1] == 2 )
            return twoPair;
        else
            return two;

    return nada;
}

int main( void ) {
    srand(time(NULL));

    int deck[52];

    for (int i = 0; i < 52; i++)
        deck[i] = i % 13;

    int hand_counts[ nTallies ] = { 0 };

    for( int r = 0; r < 100; r++ ) {
        deck_shuffle( deck );

        int p = possibility( deck ); // look at top 7 cards
        printf( " ... %2d\n", p );

        ++hand_counts[ p ];
    }

    for( int out = 0; out < nTallies; out++ )
        printf("The probability of hand type %d: is %f\n", out, (double)hand_counts[out] / 100);

    return 0;
}

相关问题