尝试执行 stem 文件时出现分段错误(核心已转储)
Segmentation fault (core dumped) while trying to execute the stem file
我有一个名为 myfile
的主干文件,它有 2 个子文件:myfile.data
和 myfile.names
.
现在我想写一个代码,它首先检查 .names
文件的最后一行,看看是否有零,如果有任何其他数字不是零然后它会说 noisy data
。如果 .names
文件的最后一行有一个零,那么我需要读取 .data 文件并对那个 .data
文件进行一些操作以产生有效的输出。
下面我给出了我尝试做的事情:
int main(int argc, char **argv)
{
char* path;
sprintf(path, "%s.names", argv[1]);
printf("...%s...\n", path);
//FILE *fp =stdin;
fp = fopen(path, "r");
char buff[1024];
int check = 0;
fseek(fp, 0, SEEK_SET);
while(!feof(fp))
{
memset(buff, 0x00, 1024);
fscanf(fp, "%[^\n]\n", buff);
}
if(strchr(buff, '0') != NULL){
check = 1;
}
if(check == 0){
printf("Noisy data...\n");
}
else if(check == 1){
char* path1;
sprintf(path1, "%s.data", argv[1]);
printf("...%s...", path1);
//FILE *fp1 = stdin;
fp1 = fopen(path1, "r");
char buf[1024];
if( fgets(buf, sizeof buf, fp1) == NULL ){
fputs("Input error\n", stderr);
return 1;
}
...
...
Produces the perfect output
}
编译成功
要执行此操作:<./executable_filename> <stemFileName> > <outputFileName>
所以每当我做的时候:./myFileName myfile output
。它在说 Segmentation fault (core dumped)
。为什么会这样?
还有一点,我的 .names 文件将包含:| Final Pseudo Deletion Count is 0.
或 | Final Pseudo Deletion Count is 1.
或 | Final Pseudo Deletion Count is 2.
,所以我想 strchr
会在这种情况下完成我的工作?
我最初尝试修改下面的代码,但在尝试了几种不同的方法后,我无法做到。
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
void * xmalloc(size_t s);
void parse_line(const char *buf, int *max, int column_count)
{
for(int i = 0; i < column_count; i++ ){
char *end;
int t = strtol(buf, &end, 10);
if( t > max[i] ){
max[i] = t;
}
if( !((i < column_count - 1 && *end == ',') || (i == column_count - 1 && *end == '\n')) ){
fprintf(stderr, "invalid input '%c' in %s", *end, buf);
exit(1);
}
buf = end + 1;
}
}
int main(int argc, char **argv)
{
char *path1;
char *path = argc > 1 ? argv[1] : "stdin";
sprintf(path, "%s.data", argv[1]);
FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
char buf[1024];
int column_count = 1;
int row_count = 1;
int *max;
/* Read first line to determine number of columns */
if( fgets(buf, sizeof buf, in) == NULL ){
fputs("Input error\n", stderr);
return 1;
}
for( const char *p = buf; *p; p++ ){
if( *p == ',' ){
column_count += 1;
}
}
max = xmalloc(column_count * sizeof *max);
for( int i = 0; i < column_count; i++ ){
max[i] = INT_MIN;
}
parse_line(buf, max, column_count);
while( fgets(buf, sizeof buf, in) != NULL ){
row_count += 1;
parse_line(buf, max, column_count);
}
if( fseek(in, 0L, SEEK_SET) ){
perror(path);
return 1;
}
printf("%d %d ", row_count, column_count - 1);
for( int i = 0; i < column_count - 1; i += 1 ){
printf("%d ", max[i]);
}
printf("%d\n", max[column_count - 1] + 1);
while( fgets(buf, sizeof buf, in) != NULL ){
char *comma = strrchr(buf, ',');
if( comma == NULL ){
fprintf(stderr, "Invalid input\n");
return 1;
}
*comma = '[=11=]';
int k = strtol(comma + 1, NULL, 10);
for(char *p = buf; *p; p++){
if( *p == ',' ) *p = ' ';
}
printf("%s %d\n", buf, k + 1);
}
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '[=11=]' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
void *
xmalloc(size_t s)
{
void *rv = malloc(s);
if( rv == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
return rv;
}
几个错误立即显现出来:
char* path;
sprintf(path, "%s.names", argv[1]);
传递给 sprintf
的缓冲区必须指向可写内存,但是 path
未初始化并且没有特别指向任何地方。参见 。您可能希望 path
成为数组而不是指针。
如果您启用警告,例如gcc -Wall -O
。那会节省你问这个问题的时间(和我回答它的时间)。
此外,由于您无法控制字符串 argv[1]
的长度,因此缓冲区的固定长度永远都不够长,因此您可能想使用 snprintf
来防止缓冲区溢出。请参阅 understanding the dangers of sprintf(...)(适用于 C++,但解决了相同的问题)。
你在 path1
再往下有同样的问题。
fp = fopen(path, "r");
如果失败,fopen
将 return NULL,并且您永远不会检查它。在这种情况下,您的程序会出现段错误。 fp1
再往下也是同样的问题。
while(!feof(fp))
这是always wrong。
fscanf(fp, "%[^\n]\n", buff);
与 sprintf
类似的溢出风险。此外,您必须检查 fscanf
是否成功;这是检查文件结尾的正确方法,代替错误的 while (!feof(fp))
.
if( fgets(buf, sizeof buf, fp1) == NULL ){
fputs("Input error\n", stderr);
return 1;
fgets
returning NULL 不一定表示“输入错误”;可能只是已到达文件末尾。
有关分段错误的原因以及如何调试它们的一般信息,另请参阅
What is a segmentation fault?
What is a debugger and how can it help me diagnose problems?
我有一个名为 myfile
的主干文件,它有 2 个子文件:myfile.data
和 myfile.names
.
现在我想写一个代码,它首先检查 .names
文件的最后一行,看看是否有零,如果有任何其他数字不是零然后它会说 noisy data
。如果 .names
文件的最后一行有一个零,那么我需要读取 .data 文件并对那个 .data
文件进行一些操作以产生有效的输出。
下面我给出了我尝试做的事情:
int main(int argc, char **argv)
{
char* path;
sprintf(path, "%s.names", argv[1]);
printf("...%s...\n", path);
//FILE *fp =stdin;
fp = fopen(path, "r");
char buff[1024];
int check = 0;
fseek(fp, 0, SEEK_SET);
while(!feof(fp))
{
memset(buff, 0x00, 1024);
fscanf(fp, "%[^\n]\n", buff);
}
if(strchr(buff, '0') != NULL){
check = 1;
}
if(check == 0){
printf("Noisy data...\n");
}
else if(check == 1){
char* path1;
sprintf(path1, "%s.data", argv[1]);
printf("...%s...", path1);
//FILE *fp1 = stdin;
fp1 = fopen(path1, "r");
char buf[1024];
if( fgets(buf, sizeof buf, fp1) == NULL ){
fputs("Input error\n", stderr);
return 1;
}
...
...
Produces the perfect output
}
编译成功
要执行此操作:<./executable_filename> <stemFileName> > <outputFileName>
所以每当我做的时候:./myFileName myfile output
。它在说 Segmentation fault (core dumped)
。为什么会这样?
还有一点,我的 .names 文件将包含:| Final Pseudo Deletion Count is 0.
或 | Final Pseudo Deletion Count is 1.
或 | Final Pseudo Deletion Count is 2.
,所以我想 strchr
会在这种情况下完成我的工作?
我最初尝试修改下面的代码,但在尝试了几种不同的方法后,我无法做到。
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE * xfopen(const char *path, const char *mode);
void * xmalloc(size_t s);
void parse_line(const char *buf, int *max, int column_count)
{
for(int i = 0; i < column_count; i++ ){
char *end;
int t = strtol(buf, &end, 10);
if( t > max[i] ){
max[i] = t;
}
if( !((i < column_count - 1 && *end == ',') || (i == column_count - 1 && *end == '\n')) ){
fprintf(stderr, "invalid input '%c' in %s", *end, buf);
exit(1);
}
buf = end + 1;
}
}
int main(int argc, char **argv)
{
char *path1;
char *path = argc > 1 ? argv[1] : "stdin";
sprintf(path, "%s.data", argv[1]);
FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
char buf[1024];
int column_count = 1;
int row_count = 1;
int *max;
/* Read first line to determine number of columns */
if( fgets(buf, sizeof buf, in) == NULL ){
fputs("Input error\n", stderr);
return 1;
}
for( const char *p = buf; *p; p++ ){
if( *p == ',' ){
column_count += 1;
}
}
max = xmalloc(column_count * sizeof *max);
for( int i = 0; i < column_count; i++ ){
max[i] = INT_MIN;
}
parse_line(buf, max, column_count);
while( fgets(buf, sizeof buf, in) != NULL ){
row_count += 1;
parse_line(buf, max, column_count);
}
if( fseek(in, 0L, SEEK_SET) ){
perror(path);
return 1;
}
printf("%d %d ", row_count, column_count - 1);
for( int i = 0; i < column_count - 1; i += 1 ){
printf("%d ", max[i]);
}
printf("%d\n", max[column_count - 1] + 1);
while( fgets(buf, sizeof buf, in) != NULL ){
char *comma = strrchr(buf, ',');
if( comma == NULL ){
fprintf(stderr, "Invalid input\n");
return 1;
}
*comma = '[=11=]';
int k = strtol(comma + 1, NULL, 10);
for(char *p = buf; *p; p++){
if( *p == ',' ) *p = ' ';
}
printf("%s %d\n", buf, k + 1);
}
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = path[0] != '-' || path[1] != '[=11=]' ? fopen(path, mode) :
*mode == 'r' ? stdin : stdout;
if( fp == NULL ){
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
void *
xmalloc(size_t s)
{
void *rv = malloc(s);
if( rv == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
return rv;
}
几个错误立即显现出来:
char* path;
sprintf(path, "%s.names", argv[1]);
传递给 sprintf
的缓冲区必须指向可写内存,但是 path
未初始化并且没有特别指向任何地方。参见 path
成为数组而不是指针。
如果您启用警告,例如gcc -Wall -O
。那会节省你问这个问题的时间(和我回答它的时间)。
此外,由于您无法控制字符串 argv[1]
的长度,因此缓冲区的固定长度永远都不够长,因此您可能想使用 snprintf
来防止缓冲区溢出。请参阅 understanding the dangers of sprintf(...)(适用于 C++,但解决了相同的问题)。
你在 path1
再往下有同样的问题。
fp = fopen(path, "r");
如果失败,fopen
将 return NULL,并且您永远不会检查它。在这种情况下,您的程序会出现段错误。 fp1
再往下也是同样的问题。
while(!feof(fp))
这是always wrong。
fscanf(fp, "%[^\n]\n", buff);
与 sprintf
类似的溢出风险。此外,您必须检查 fscanf
是否成功;这是检查文件结尾的正确方法,代替错误的 while (!feof(fp))
.
if( fgets(buf, sizeof buf, fp1) == NULL ){
fputs("Input error\n", stderr);
return 1;
fgets
returning NULL 不一定表示“输入错误”;可能只是已到达文件末尾。
有关分段错误的原因以及如何调试它们的一般信息,另请参阅
What is a segmentation fault?
What is a debugger and how can it help me diagnose problems?