代码之家  ›  专栏  ›  技术社区  ›  LucasMaliszewski

XCODE:Thread 1:EXC_BAD_访问(代码=1,地址=0x68)在fscanf上

  •  0
  • LucasMaliszewski  · 技术社区  · 2 年前

    我正在使用下面的代码,我收到了 Thread 1: EXC_BAD_ACCESS (code=1, address=0x68) 错误我有哪些方法可以更好地执行此任务?我只是加载一个txt文件,它有大约500000个数字,每个数字都在一个新行上。我看了一些资源如何做到这一点,但我最终发现了这些奇怪之处。我希望c大师能帮我。

    #include <stdio.h>
    #include <time.h>
    #include <limits.h>
    #include <math.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    #define COUNT_ARRAY_LENGTH 10
    #define MAX_NUMBER 500001
    
    int *load_file(){
        FILE *file;
        file = fopen("somefile.txt", "r");
        int a[MAX_NUMBER];
    
        int i=0;
        int num;
        while(fscanf(file, "%d", &num) > 0) {
            a[i] = num;
            i++;
        }
        fclose(file);
        return a;
    }
    
    int main(int argc, const char *argv[])
    {
        int *a;
        a = load_file();
        for(int i = 0; i < MAX_NUMBER; i++){
            printf("%d\n", a[i]);
        }
        return 0;
    }
    
    1 回复  |  直到 2 年前
        1
  •  1
  •   Jonathan Leffler    2 年前

    将评论转化为答案。

    我的直接猜测是,您无法打开文件,这是一个您没有检查的错误,必须始终检查。文件擅离职守,或者程序从错误的目录运行,或者它们拥有错误的权限。

    if (file == NULL)
    {
        fprintf(stderr, "Failed to open file '%' for reading\n", "somefile.txt");
        exit(EXIT_FAILURE);
    }
    

    文件名的重复文本显示了为什么不应该将字符串文本作为文件名传递给 fopen() ; 您应该有一个变量,这样您也可以在错误消息中报告文件名,而无需重复。

    const char *filename = "somefile.txt";
    if ((file = fopen(filename, "r")) == NULL)
    {
        fprintf(stderr, "Failed to open file '%' for reading\n", filename); n. 
        exit(EXIT_FAILURE);
    }
    

    实际上,您可能应该将要加载的文件名传递给 load_file() 函数,以便更轻松地更改它(例如,通过命令行参数)。也就是传递数组,以及数组的大小。这给了你一个更通用的功能,一个更容易适应其他用途的功能。

    你也可以 #include <errno.h> #include <string.h> 使用 strerror(errno) 打印系统错误消息,为用户提供更多帮助(但知道文件名是朝着正确方向迈出的一大步)。

    还有,你应该 while (i < MAX_NUMBER && fscanf(file, "%d", &num) > 0) 这样就不会使数组溢出。

    此外,还将在load_file()中返回本地数组的地址 you can't do that safely .在中定义数组 main() 并将指针作为参数传递。你的 main() 还假定数组已填充。修改 加载_文件() 返回加载了多少个号码,这样就不会访问卸载的号码。

    将所有这些变化放在一起可能会产生:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_NUMBER 500001
    
    static size_t load_file(const char *filename, size_t arrsiz, int *array)
    {
        FILE *file;
        if ((file = fopen(filename, "r")) == NULL)
        {
            fprintf(stderr, "Failed to open file '%s' for reading\n", filename);
            exit(EXIT_FAILURE);
        }
    
        size_t i = 0;
        int num;
        while (i < arrsiz && fscanf(file, "%d", &num) > 0)
            array[i++] = num;
    
        fclose(file);
    
        return i;
    }
    
    int main(void)
    {
        int a[MAX_NUMBER];
        size_t num = load_file("somefile.txt", MAX_NUMBER, a);
    
        for (size_t i = 0; i < num; i++)
            printf("%d\n", a[i]);
    
        return 0;
    }
    

    已编译但未运行。

    您可以这样处理命令行参数:

    int main(int argc, char **argv)
    {
        if (argc > 2)
        {
            fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
            exit(EXIT_FAILURE);
        }
        const char *filename = (argc == 2) ? argv[1] : "somefile.txt";
    
        int a[MAX_NUMBER];
        size_t num = load_file(filename, MAX_NUMBER, a);
    
        for (size_t i = 0; i < num; i++)
            printf("%d\n", a[i]);
    
        return 0;
    }
    

    或者你可以允许一个以上的参数,并对它们进行迭代。 有时,最好是在窗口中打开和关闭文件 main() 并将打开的文件流传递给函数。然后你可以阅读 stdin 如果没有命令行参数。选择太多了!