C 程序接收信号 SIGTRAP,每 3 次尝试运行良好
C Program receives signal SIGTRAP, works well on every 3rd try
我正在用 C 编写 "Who want's to be a millionaire" 游戏,其中包含 SDL。
我已经开发了 SDL 图形并分别进行了数据处理。
后者是我遇到的问题。
它得到一个大约 5000 行长的 .csv 文件,并借助动态分配的内存将细节放入结构中。
然后它被打印到控制台。
但是,它每 3 次左右才起作用。
其他时候,程序会冻结。
试过调试,它说:
Program received signal SIGTRAP, Trace/breakpoint trap.
认为我将问题缩小到这部分:
while ((read = getline(&line, &n, kerdes)) != -1) {
sp = p = line;
field = 0;
// The below line triggers the signal
questions[cnt] = (Question*) malloc(sizeof(Question));
// Cuts
while (*p != '[=10=]') {
if (*p == ',') {
*p = 0;
if (field == 0) questions[cnt]->nth = atoi(sp);
if (field == 1) questions[cnt]->question_to = strdup(sp);
if (field == 2) questions[cnt]->answer_a = strdup(sp);
if (field == 3) questions[cnt]->answer_b = strdup(sp);
if (field == 4) questions[cnt]->answer_c = strdup(sp);
if (field == 5) questions[cnt]->answer_d = strdup(sp);
if (field == 6) questions[cnt]->answer_r = strdup(sp);
if (field == 7) questions[cnt]->cat = strdup(sp);
*p = ',';
sp = p + 1;
field++;
}
p++;
}
cnt++;
}
getline
函数来自 this answer:
size_t getline(char **lineptr, size_t *n, FILE *stream) {
char *bufptr = NULL;
char *p = bufptr;
size_t size;
int c;
if (lineptr == NULL) {
return -1;
}
if (stream == NULL) {
return -1;
}
if (n == NULL) {
return -1;
}
bufptr = *lineptr;
size = *n;
c = fgetc(stream);
if (c == EOF) {
return -1;
}
if (bufptr == NULL) {
bufptr = malloc(128);
if (bufptr == NULL) {
return -1;
}
size = 128;
}
p = bufptr;
while(c != EOF) {
if ((p - bufptr) > (size - 1)) {
size = size + 128;
bufptr = realloc(bufptr, size);
if (bufptr == NULL) {
return -1;
}
}
*p++ = c;
if (c == '\n') {
break;
}
c = fgetc(stream);
}
*p++ = '[=11=]';
*lineptr = bufptr;
*n = size;
return p - bufptr - 1;
}
我做了 - 希望 - 彻底搜索 Whosebug,但没有成功。
什么可能导致问题?
在我看来,过度索引并不是背后的原因,而且 free() 使用得很好。
请在 pastebin 上找到整个 .c 文件,然后是 link:
Click here
CSV 文件(非英语)可使用以下 link 访问:Click here
问题出在getline
代码中,那是非常b0rken。我用 POSIX 标准 getline
替换了它,它完美地工作。问题是这里的 realloc
代码:
p = bufptr;
while(c != EOF) {
if ((p - bufptr) > (size - 1)) {
size = size + 128;
bufptr = realloc(bufptr, size);
if (bufptr == NULL) {
return -1;
}
}
*p++ = c;
if (c == '\n') {
break;
}
c = fgetc(stream);
}
realloc
可以(很可能 将 )return 指向 new 缓冲区的指针,但是 p
将指向旧缓冲区,因此行 *p++ = c;
将具有 未定义的行为.
I have now provided a (hopefully) fixed version of that getline
implementation in my answer to the getline question.
我正在用 C 编写 "Who want's to be a millionaire" 游戏,其中包含 SDL。 我已经开发了 SDL 图形并分别进行了数据处理。 后者是我遇到的问题。
它得到一个大约 5000 行长的 .csv 文件,并借助动态分配的内存将细节放入结构中。 然后它被打印到控制台。 但是,它每 3 次左右才起作用。 其他时候,程序会冻结。 试过调试,它说:
Program received signal SIGTRAP, Trace/breakpoint trap.
认为我将问题缩小到这部分:
while ((read = getline(&line, &n, kerdes)) != -1) {
sp = p = line;
field = 0;
// The below line triggers the signal
questions[cnt] = (Question*) malloc(sizeof(Question));
// Cuts
while (*p != '[=10=]') {
if (*p == ',') {
*p = 0;
if (field == 0) questions[cnt]->nth = atoi(sp);
if (field == 1) questions[cnt]->question_to = strdup(sp);
if (field == 2) questions[cnt]->answer_a = strdup(sp);
if (field == 3) questions[cnt]->answer_b = strdup(sp);
if (field == 4) questions[cnt]->answer_c = strdup(sp);
if (field == 5) questions[cnt]->answer_d = strdup(sp);
if (field == 6) questions[cnt]->answer_r = strdup(sp);
if (field == 7) questions[cnt]->cat = strdup(sp);
*p = ',';
sp = p + 1;
field++;
}
p++;
}
cnt++;
}
getline
函数来自 this answer:
size_t getline(char **lineptr, size_t *n, FILE *stream) {
char *bufptr = NULL;
char *p = bufptr;
size_t size;
int c;
if (lineptr == NULL) {
return -1;
}
if (stream == NULL) {
return -1;
}
if (n == NULL) {
return -1;
}
bufptr = *lineptr;
size = *n;
c = fgetc(stream);
if (c == EOF) {
return -1;
}
if (bufptr == NULL) {
bufptr = malloc(128);
if (bufptr == NULL) {
return -1;
}
size = 128;
}
p = bufptr;
while(c != EOF) {
if ((p - bufptr) > (size - 1)) {
size = size + 128;
bufptr = realloc(bufptr, size);
if (bufptr == NULL) {
return -1;
}
}
*p++ = c;
if (c == '\n') {
break;
}
c = fgetc(stream);
}
*p++ = '[=11=]';
*lineptr = bufptr;
*n = size;
return p - bufptr - 1;
}
我做了 - 希望 - 彻底搜索 Whosebug,但没有成功。
什么可能导致问题?
在我看来,过度索引并不是背后的原因,而且 free() 使用得很好。
请在 pastebin 上找到整个 .c 文件,然后是 link: Click here
CSV 文件(非英语)可使用以下 link 访问:Click here
问题出在getline
代码中,那是非常b0rken。我用 POSIX 标准 getline
替换了它,它完美地工作。问题是这里的 realloc
代码:
p = bufptr;
while(c != EOF) {
if ((p - bufptr) > (size - 1)) {
size = size + 128;
bufptr = realloc(bufptr, size);
if (bufptr == NULL) {
return -1;
}
}
*p++ = c;
if (c == '\n') {
break;
}
c = fgetc(stream);
}
realloc
可以(很可能 将 )return 指向 new 缓冲区的指针,但是 p
将指向旧缓冲区,因此行 *p++ = c;
将具有 未定义的行为.
I have now provided a (hopefully) fixed version of that getline
implementation in my answer to the getline question.