2016-02-14 55 views
-1

的test1.c:打开文件会导致不同的结果

int main(int argc, char *argv[]) 
    { 
     FILE* fp = fopen("test.txt","rw"); 
     int n,m,q; 
     scanf(" %d%d%d",&n,&m,&q); 
     struct test_t test; 
     while (fscanf(fp,"%d%s%d%d%d%d%d%d%d%*d",&test.line,test.data,&test.number[0],&test.number[1],&test.number[2],&test.number[3],&test.number[4],&test.number[5],&test.number[6])!=EOF) { 
       //do something..... 
     } 
     return 0; 
    } 

的test2.c中:

int main(int argc, char *argv[]) 
{ 
    int n,m,q; 
    scanf(" %d%d%d",&n,&m,&q); 
    struct test_t test; 
    FILE* fp = fopen("test.txt","rw"); 
    while (fscanf(fp,"%d%s%d%d%d%d%d%d%d%*d",&test.line,test.data,&test.number[0],&test.number[1],&test.number[2],&test.number[3],&test.number[4],&test.number[5],&test.number[6])!=EOF) { 
      //do something.... 
    } 
    return 0; 
} 

test_t的定义:

struct test_t { 
    int line; 
    char* data; 
    int number[7]; 
}; 

我的测试。 txt:

141 2015-12-05 19 16 35 06 34 46 09 00 
124 2015-12-08 49 25 10 09 40 48 32 00 
143 2015-12-10 09 29 24 47 32 34 42 00 

当我使用test1.c时,我得到了分段错误。但是当我使用test2.c时,它运行良好。只改变了FILE* fp = fopen("test.txt","rw");这一行。引起这种差别的原因是什么。

+0

您的代码不会编译,因为编译器不知道'size_t'的大小。 –

+0

@AshishAhuja我没有发布'test_t'的定义,我现在会发布它 – icecity96

+0

你为什么不发布它?总是发布编译的代码! –

回答

2

您正在调用UB,因为您从不为char* data;分配内存。修正:

  1. mallocwhile循环之前足够的内存:

    test.data = malloc(32); 
    if(!test.data) 
    { 
        fprintf(stderr, "malloc failed...Bailing out!\n"); 
        exit(-1); 
    } 
    

    而且其使用后,

    free(test.data); 
    
  2. 使用预定义的大小,而不是指向char的数组:

    char data[32]; 
    

而且,@AshishAhuja said,检查fopen也返回值。

2

那么,当你从不同的地方运行程序时,该文件在该位置不存在的可能性很高。因此,检查fopen是否返回NULL。这样做:

FILE* fp = fopen("test.txt","rw"); 
if (fp == NULL) { 
    printf ("Error, file does not exist\n"); 
    exit (1); 
} 

打开不存在是没有问题的,因为fopen只会返回NULL的文件。尝试读取或写入它将导致分段错误和核心转储。


而且,你永远不会为char *data分配内存,这可能会导致问题。要正确分配和释放,请参阅@CoolGuy's答案。

+1

更糟糕的是:'test.data'未初始化:将其作为scanf'%s'格式的接收器传递,肯定会调用未定义的行为。初始化分配内存是一种可能的解决方案。 – chqrlie

相关问题