繁体   English   中英

初始化带有数组的结构时出现分段错误

[英]Segmentation fault when initializing struct w/ arrays

我正在用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上是这样)。

有人可以帮忙弄清楚这里发生的事情吗?

这里:

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个元素。 您似乎正在断断续续,因为这会使系统中的count变为负数,因为您已将其定义为在系统上签名的char

您可以将其定义为int ,当我这样做时,segfault对我来说就消失了,但是您仍然无法超出数组的范围,因此使用count的逻辑显然存在问题。 或者,更有用的是,您有一对循环,可吐出152个字母,但您只为其中的100个预留了内存,因此您制作的字母多于空间。

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

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

b.tiles[count] = letter;

要在gdb中看到此内容:

gdb blah
b 21
cond 1 count >= 100
run

如果你去高足以与count上面,你会在堆栈上垃圾的返回地址,这就是为什么你在段错误的return

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM