使用大型数组时如何防止计算器溢出错误? C 阅读Modern C并从现有开源软件中汲取灵感,

问题描述

我有代码可以将 60000 行排序为每种数据类型的数组

它适用于 1 行,但在循环遍历多行时出现堆栈溢出错误

这就是我定义结构的方式。

int main(void) {

typedef struct values{
    struct values* Time;
    struct values* RESP;
    struct values* PLETH;
    struct values* II;
    struct values* V;
    struct values* AVR;
    struct values* ABP;     
}values;

    values array[60000];

这是数据文件的示例

enter image description here

这是我用来读取文件代码

char line[80];
FILE* pointer = fopen("bidmc_04_Signals.csv","r");
fgets(line,60000,pointer);//moves pointer past 1st line
printf(line); 
fgets(line,pointer);
printf(line);

这是我代码的数组生成部分

    int i = 0;
    int c = 0;
    int row_count = 0;
    int row_limit = 60000;
        while (row_count < row_limit) {
            fgets(line,60,pointer);
            char*p = strtok(line,",");
            c = 0;
            while (p != NULL)
            {               
                if (c == 0)
                    strcpy(array[i].Time,p);
                    array[i].Time = malloc(10000);

                if (c == 1)
                    strcpy(array[i].RESP,p);
                    array[i].RESP = malloc(10000);

                if (c == 2)
                    strcpy(array[i].PLETH,p);
                    array[i].PLETH = malloc(10000);

                if (c == 3)
                    strcpy(array[i].II,p);
                    array[i].II = malloc(10000);

                if (c == 4)
                    strcpy(array[i].V,p);
                    array[i].V = malloc(10000);

                if (c == 5)
                    strcpy(array[i].AVR,p);
                    array[i].AVR = malloc(10000);

                if (c == 6)
                    strcpy(array[i].ABP,p);
                    array[i].ABP = malloc(10000);

                p = strtok(NULL,");
                c++;
                }

            row_count++;
            i++;        
        }
        
    fclose(pointer);
    for (i = 0; i < 60000; i++) {
    
    free(array[i].RESP);
    free(array[i].PLETH);
    free(array[i].II);
    free(array[i].V);
    free(array[i].AVR);
    free(array[i].ABP);
}

}

如您所见,我尝试使用 malloc() 将数组数据移动到堆,但没有奏效。 如何防止代码出现堆栈溢出错误

解决方法

使用更多C dynamic memory allocation

Call stacks 通常限制为 1 兆字节并包含您的 automatic variable。您的调用范围(对于您的 array)很大,而且您可能有一个 stack overflow

你需要为你的数组使用 calloc(3) 并将它声明为 value*array;(当然,改名,它变成了一个指针,而不是一个数组)。

所以

 value*ptr = calloc(60000,sizeof(value));
 if (!ptr) { perror("calloc failure"); exit(EXIT_FAILURE); };

然后使用 ptr 而不是 array。请注意 malloc(3)calloc 可能会失败。另请参阅 errno(3)perror(3)

不要忘记free(ptr)

阅读Modern C并从现有开源软件中汲取灵感,

喜欢 GNU makeGTK。另请阅读一些 C 标准草案,例如n1570

还要仔细阅读 C 编译器的文档,例如GCC 和您的调试器,例如GDB。如果您可以使用 GCC,请使用 gcc -Wall -Wextra -g 进行编译以获得多个警告,甚至可能使用 -fanalyzer 和其他选项,例如 -Wstack-usage=2048

考虑使用 valgrindClang static analyzer

在 Linux 上,除了 strace(1) 之外,ltrace(1)gdb(1) 可能会有所帮助。您也可以考虑使用 Frama-C

我有代码可以对 60000 行进行排序......

然后考虑使用 qsort(3)qsort_r

也读一本好的operating system textbook

附注。您可能对bismon(见this draft report)和RefPerSys感兴趣。在这两种情况下,请通过电子邮件(英语、法语或俄语)与我联系 basile@starynkevitch.net

,

除了另一个答案之外,这些行(以及其他 5 个类似的集合)

if (c == 0)
    strcpy(array[i].Time,p);
    array[i].Time = malloc(10000);

缺少大括号,错误的方式,并分配了过多的内存。请改为

if (c == 0) {             // indentation alone does not make a code block
    array[i].Time = malloc(strlen(p) + 1);   // allocate the right amount
    strcpy(array[i].Time,p);                // AFTER allocation
}

还有这两行

fgets(line,60000,pointer); 
...
fgets(line,60,pointer); 

应该是

fgets(line,sizeof line,pointer);