初始化struct w / arrays时出现分段错误

时间:2016-01-04 00:38:41

标签: c struct segmentation-fault

我在C中写了一个ncurses Scrabble克隆。

我已经写了一些代码来代表一个包,这是一个可以将字符拉出来的洗牌字符的来源,就像在现实生活中从包中拉出随机的瓷砖一样。

我的代码适用于OS X - 但是当我尝试在Debian机器上编译时,它给了我这个直截了当的消息:

~/nscrabble $ ./scrabble
Segmentation fault

我已使用gdb尝试诊断问题。似乎段错误是由return语句引起的:

(gdb) run
Starting program: /home/jay/nscrabble/scrabble 

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400ca8 in bag () at bag.c:53
53          return b;
(gdb) 

你去吧。这是代码(bag.cbag.h) 这是bag.h -

#ifndef BAG_H_INCLUDED
#define BAG_H_INCLUDED

/*
 * This array states how many times each
 * letter should show up in the bag.
 *
 * distributions[0]     Number of As
 * distributions[1]     Number of Bs
 * ...
 * distributions[25]    Number of Zs
 * distributions[26]    Number of blank tiles
 */
const short distributions[27];

/*
 * The bag is the repository of tiles in Scrabble.
 * I didn't want to deal with storing pointers
 * and freeing them constantly, so I decided to
 * store chars.
 */
typedef struct bag {
        char tiles[100];
        size_t top;

        /*
         * Get a tile letter out of the bag.
         * It removes the letter from the bag.
         */
        char (*pop)( struct bag* );
} bag_t;

/*
 * The constructor.
 * Get a new bag using this.
 */
struct bag bag();



char bg_pop( struct bag* );

#endif

这里bag.c -

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "bag.h"

const short distributions[27] = {
        9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 
        6, 4, 6, 4, 2, 2, 1, 2, 1, 2
};

char bg_pop( struct bag* b )
{
        return b->tiles[b->top--];
}

struct bag bag()
{
        struct bag b;
        for( char letter = 'A', count = 0; letter <= ']'; letter++ ) {
                for(int i = 0; i < distributions[letter - 65]; i++, count++)
                        b.tiles[count] = letter;
        }
        srand( time(NULL) );
        for( int i = 0; i < 3; i++, rand() )
                ;
        for( int i = 0; i < 98; i++ ) {
                int n = (rand() % (100 - i)) + i;
                char temp = b.tiles[i];
                b.tiles[i] = b.tiles[n];
                b.tiles[n] = temp;
        }
        b.top = 100;
        b.pop = bg_pop;
        return b;
}

scrabble.c:

#include <stdio.h>
#include "bag.h"

int main( int argc, const char** argv )
{
        struct bag b = bag();

        for( int i = 0; i < 100; i++ )
                printf("%3c", b.tiles[i]);
}

我知道改组正在进行(至少在OS X上)。

有人可以帮助阐明这里发生的事情吗?

2 个答案:

答案 0 :(得分:1)

下面:

for( char letter = 'A', count = 0; letter <= ']'; letter++ ) {
    for( int i = 0; i < distributions[ letter - 65 ]; i++, count++ ) {
        b.tiles[count] = letter;
    }
}

如果您打印出count的值,您会看到它高达152,远高于数组中的100个元素。您似乎是segfaulting,因为这会使count在您的系统上变为负数,因为您已将其定义为char,并在您的系统上签名。

你可以将它定义为int,当我这样做时,segfault就会消失,但是你的数组仍然会超出范围,所以你的逻辑显然有问题{ {1}},在这里。或者,更有用的是,你有一对吐出152个字母的循环,但是你只为其中的100个字节留出了内存,所以你制作的字母多于你有空格的字母。

如果您将count更改为letter <= ']'(因为letter <= '['紧跟在ASCII表格中的'['之后),那么一旦'Z'达到100,您的循环就会正确退出,你应该被设置。

答案 1 :(得分:0)

您在第21行超出了数组的范围:

b.tiles[count] = letter;

使用gdb查看此内容:

gdb blah
b 21
cond 1 count >= 100
run

如果您使用上面的count达到足够高,则会将堆栈中的返回地址废弃,这就是您在return

上出现段错误的原因