C程序:[完成]在2.322秒内以代码= 3221225477退出Calloc / Free / Segmenation错误?

如何解决C程序:[完成]在2.322秒内以代码= 3221225477退出Calloc / Free / Segmenation错误?

我正在使用C程序来处理大量CSV数据。测试文件很小,运行良好。但是,当文件大小增加时,它将开始失败。取决于我是使用gcc还是minGW的gcc进行编译,它会因分段错误或3221225477 / 0xC0000005在不同位置而失败,始终为:

if (fclose(fp)) { 
    printf("Error closing file: %s,%s,%d.\n",fileName,__func__,__LINE__);
    exit(300); 
}

请注意,它不会超过fclose()。或其中之一:

data_PE_T12         = calloc(width_T*dataDepthDay,sizeof(*data_PE_T12));

很长,所以我将尝试展示相关部分。首先是Main函数:

#include <stdio.h>
#include <string.h> // strtok
#include <stdlib.h> // atoi & atof
#include <time.h>   // time functions
#include <math.h>   // expf()


...
// Array Sizes
static int dataDepth,dataDepthDay;                                                                                             
static int fromTime,toTime;                                                                                                    
static int width,width_T,width_H,width_C;


// Array Pointers
static int                      *timeArray,*timeArrayDay,*timeArrayPE;                                          
static struct sensorHeader_t    *headerArray,*headerArray_T,*headerArray_H,*headerArray_C;                 

// of depth dataDepthDay
static float                    *data_E_T25,*data_E_T30;        
static float                    *data_E_T12,*data_E_T18,*data_E_H60,*data_E_H70,*data_E_C1500;
static float                    *data_PE_T12,*data_PE_T18,*data_PE_H60,*data_PE_H70,*data_PE_C1500;
... plus loads more.

// functions
void  grabDepth(void);                  // OK
void  grabPayload(void);                // OK
... plus loads more.


int main(int argc,char **argv)
{

// Grab Input File Name 
    if (argc == 2) {
        strcpy(rawFile,"in/");
        strcat(rawFile,argv[1]);
    } else { // dev
        strcpy(rawFile,"in/sensor_report.csv");
    }

    printf("size max = %d",__SIZE_MAX__);

// Parse and Copy File
    grabDepth();
    grabPayload();

// Run functions
    genRawData();       // Raw T,H & C files   
    genExposureE();     // 
    genExposureAPE();   // 


    return 0;
}

接下来调用的第一个函数。这将打开主输入文件,并提取许多数组宽度和深度,这些宽度和深度用于对已声明为静态指针的数组进行调用。这样做的想法是,随着文件大小的增加,这将使内存的处理变得美观而灵活。

void grabDepth(void)
{
// 1. Open File
    FILE *fp = fopen(rawFile,"r");
    char buf[15000]; // Big enough to deal with lots of devices.
    
    if (!fp) {
        printf("Can't open the file: %s: %s,rawFile,__LINE__);
        exit(100);
    }
    
    while (fgets (buf,sizeof(buf),fp)) {
        int lineLen = strlen(buf);
        int colNum = 1;
        char *field = strtok(buf,",");

        if (field && strcmp(field,"From") == 0) {
            // printf("\n\n*** row 2 ***\n\n");
            // int fromTime,toTime = 0;
            
            while (field) {
                if (colNum == 2) {
                    fromTime = atof(field);
                }
                
                if (colNum == 4) {
                    toTime = atof(field);
                }
                field = strtok(NULL,");
                colNum++;
            }
            
            // printf("FromTime = %d. ToTime = %d.\n",fromTime,toTime);
            dataDepth = ( toTime - fromTime )/900;
            // printf("dataDepth = %d.\n",dataDepth);
            continue; // to next iteration. 
             
        }
        
// 3. Grab file width from line 10 (commsType) Check if buf Overruns too
        if (field && strcmp(field,"TimeStamp") == 0) {
            // First Check Line is long enough!
            if (lineLen == sizeof(buf)-1) { // buf has overrun!
                printf("File Read-Line Overrun: %s,__LINE__);
                exit(200);
            }
            // printf("Line Length = %d\n",lineLen);
            // printf("Buf Size    = %d\n",sizeof(buf));
            width = -2; // ignore timestamps : I ballsed up the commas in csv file (-2 instead of -1)
            while (field) {
                if(field = strtok(NULL,")) {
                    width ++;
                }
            }
            break; // out of loop!
        }
    }
    
    //dataDepthDay = dataDepth/96 + (dataDepth % 96 !=0); // round up?!
    dataDepthDay = dataDepth/96;                        // round down?!
    printf("\n 1. grabDepth() Results\n");
    printf(  "------------------------\n");
    printf("Raw Data Width     = %d\n",width);
    printf("Raw Data Depth     = %d\n",dataDepth);
    printf("dataDepthDay Depth = %d\n\n",dataDepthDay);

    if (fclose(fp)) { 
        printf("Error closing file: %s,__LINE__);
        exit(300); 
    }
}

之后,它只是依次调用一个函数,所有这些函数都遵循以下一般模式:

void _genRawData(char* sensorType,struct sensorHeader_t *sensorHeader,float *dataArray,int *timeArray,size_t dataDepth,size_t width) {
    FILE *fp;
    strcpy(fileName,"out/");
    strcat(fileName,sensorType);
    strcat(fileName,"_raw.csv");
    fp = fopen(fileName,"w");

    // check file opened OK. 
    if (fp == NULL) {
        printf("Error! Couldn't Create file: %s\n",fileName);
        return;
    }
    printf("building file : %s\n",fileName);
    

    // Allocate Memory
    timeArrayDay    = calloc(dataDepthDay,sizeof(*timeArrayDay));
    timeArrayPE     = calloc(dataDepthDay,sizeof(*timeArrayPE)); // xxxx same array as day time array!?
    data_E_T12      = calloc(width_T*dataDepthDay,sizeof(*data_E_T12));
    data_E_T18      = calloc(width_T*dataDepthDay,sizeof(*data_E_T18));
    data_E_H60      = calloc(width_H*dataDepthDay,sizeof(*data_E_H60));
    data_E_H70      = calloc(width_H*dataDepthDay,sizeof(*data_E_H70));
    
    // do stuff and build new arrays up and put into files...
    
    
    
        if (fclose(fp)) { 
        printf("Error closing file: %s,__LINE__);
        exit(300); 
    }
}

我在每个2-D数组上只调用一次calloc,为了调试,我删除了free()调用。

我认为我在内存管理上做错了什么,当数组大小超过某个点时,这让我很痛苦,但是我无法弄清楚出了什么问题。我试图确保我访问的内存已正确分配,并且可以在功能强大的实际计算机(通常是嵌入式人员)上工作,我不希望OS发出数据时会遇到任何问题吗?没有足够的空间!?

解决方法

如果结果对其他人有用。我怀疑calloc和分配的内存的后续使用存在问题。所以我尝试了两件事:

1:检查代码中的内存使用情况:

// Add Values & Write Line on new Day & Reset Accumulator
for (i=0; i < dataDepth; i++) {
    for (j=0; j < width; j++) {
            if (newDay) {
                fprintf(fp,",%.2f",APE_Accum[j]);
                data_E_Array[(data_E_Index-1)*width+j] = APE_Accum[j];
                if ((data_E_Index-1)*width+j+1 > (width_T*dataDepthDay)) {
                    printf("Oh bugger...\n");
                    printf("width_T*dataDepthDay = %d\n",width_T*dataDepthDay);
                    printf("data_E_Index-1 = %d\n",data_E_Index-1);
                    printf("width = %d\n",width);
                    printf("dataDepthDay = %d\n",dataDepthDay);
                    printf("width_T = %d\n",width_T);
                    printf("j = %d\n\n",j);

真正凌乱的代码,因此您可以了解我如何失去对数组范围的跟踪。基本上,很明显我搞砸了对愈伤组织大小的计算。我可能会发现这样的问题,但是我认为这不是我的问题的可行答案,因为它可以扩展到更大或更复杂的代码。

2:瓦尔格隆德。遵循@dbush的建议。我移至Ubuntu,安装了Valgrind,然后重新编译...

$ sudo apt install valgrind
$ ps aux | grep-i apt
$ gcc -o graphomatic ./graphomatic.c -lm -g
$ valgrind --leak-check=full --show-leak-kinds=all --verbose --track-origins=yes --log-file=valgrind-log
$ less valgrind-log

鲍勃是你的叔叔。问题跳出来了。我需要添加-lm以链接到数学库。然后使用-g来确保Valgrind输出中包含行号。

==15878== Invalid write of size 4
==15878==    at 0x4038EA: _genExposureE (graphomatic.c:867)
==15878==    by 0x404A0C: genExposureE (graphomatic.c:1235)
==15878==    by 0x400EAA: main (graphomatic.c:122)
==15878==  Address 0x75cd604 is 0 bytes after a block of size 660 alloc'd
==15878==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15878==    by 0x404911: genExposureE (graphomatic.c:1222)
==15878==    by 0x400EAA: main (graphomatic.c:122)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-