C:为什么我在一个案例中遇到分段错误而在另一个案例中没有?

时间:2013-12-10 13:45:39

标签: c segmentation-fault

我是C新手所以我相信由于指针和内存分配缺乏基础知识,我的代码中出现了一个新手错误。

我有一个表示数字数据的二进制文件,我正在尝试读取和存储该数据。 这是打开文件的代码的第一部分,在文件中读取少量数字,用于为struct emxArray_real_T分配足够的内存。

STRUCT:

struct emxArray_real_T
{
    real_T *data;
    int32_T *size;
    int32_T allocatedSize;
    int32_T numDimensions;
    boolean_T canFreeData;
}

主要的第一部分:

# include <stdio.h>
# include <stdlib.h> /*atoi*/
# include <assert.h>

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

//Variable declaration
unsigned short numOfSums;
unsigned long chSum, countRSN, countPeriods;
int i,j;
FILE *file;

//Open file
file = fopen("testBin.bin","rb");

//Read first number that tells how many items to skip
fread(&numOfSums, 2, 1,file);
//Skip that many items
for (i=0;i<numOfSums;i++){
    fread(&chSum,4,1,file);
}
//Read next two numbers
fread(&countRSN,4,1,file);
fread(&countPeriods,4,1,file);

//Allocate enaugh space based on the size of countRSN and countPeriods
struct emxArray_real_T* Sa_1 = malloc(sizeof(*Sa_1)*1);
assert(Sa_1 != NULL);
Sa_1->data=malloc(sizeof(real_T)*countRSN*countPeriods);
Sa_1->size=malloc(sizeof(int32_T)*2);
Sa_1->allocatedSize=(sizeof(int32_T)*1);
Sa_1->size[0]=countRSN;
Sa_1->size[1]=countPeriods;

struct emxArray_real_T *Sa_2;
Sa_2=(struct emxArray_real_T*)malloc(sizeof(struct emxArray_real_T)*1);
assert(Sa_2 != NULL);
Sa_2->data=(real_T*)malloc(sizeof(real_T)*countRSN*countPeriods);
Sa_2->size=malloc(sizeof(int32_T)*2);
Sa_2->allocatedSize=(sizeof(int32_T)*1);
Sa_2->size[0]=countRSN;
Sa_2->size[1]=countPeriods;

struct emxArray_real_T *sVs30;
sVs30=(struct emxArray_real_T*)malloc(sizeof(struct emxArray_real_T));
sVs30->data=malloc(sizeof(real_T)*countRSN);
sVs30->size=malloc(sizeof(int32_T)*1);
sVs30->allocatedSize=(sizeof(int32_T)*1);
sVs30->size[0]=countRSN;

这是问题所在。如果我试图存储我的数据并转置它,因为它的顺序不正确,我会得到分段错误,

for (i=0;i<countRSN;i++){
    for (j=0;j<countPeriods;j++){
        fread(&Sa_1->data[countRSN*j+i],8,1,file);
    }
}

如果我这样尝试,它就可以了:

for (i=0;i<countRSN*countPeriods;i++){
    fread(&Sa_1->data[i],8,1,file);
}

.
.
.

fclose(file);

free(Sa_1);
free(Sa_2);
free(sVs30);
return 0;
}

3 个答案:

答案 0 :(得分:0)

每次调用fread,您都会读取8个字节并将其写入数组。在我看来,你把它们存放在正确的位置。如果sizeof(real_T)小于8,则必须预期出现分段错误。

如果sizeof(real_T)小于8,说它的大小为4 *,&Sa_1->data[countRSN*countPeriods-1]将在有效位置写入4个字节中的4个,其他4个字节将写入分配范围之外

为什么代码会在一个案例中崩溃而另一个案例却不会崩溃?首先,通过访问未分配的内存,您处于未定义的行为范围内。该程序不再需要以明确定义的方式运行。其次,如果文件流已经到达结尾,fread不会写入缓冲区。在您的示例中工作的代码仅在文件足够长时写入最后一个地址。

*在Matlab中,real_T是4或8个字节,具体取决于定义。如果它是4个字节,那么op给出的代码应该抛出一个段错误。

答案 1 :(得分:0)

您假设的类型大小。在你使用4,2,8等的任何地方使用sizeof。同时确保fread可以使用short int,我怀疑

答案 2 :(得分:0)

struct emxArray_real_T* Sa_1 = malloc(sizeof(*Sa_1)*1);

struct emxArray_real_T* Sa_1 = malloc(sizeof(struct emxArray_real_T));