[英]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.c
和bag.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.