LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   why segmentation fault? (https://www.linuxquestions.org/questions/programming-9/why-segmentation-fault-658658/)

nanxy 07-27-2008 09:48 PM

why segmentation fault?
 
HI~ GUYS I wrote a C program and I tried to compile it but it always remind me that there is a segmentation fault in line 49.Can anyone help me to find it out? thank you~


1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4
5 typedef struct _HEADER {
6
7 int num1;
8 int num2;
9 int num3;
10 int num4;
11
12 }HEADER;
13
14 void **Allocate2D(long int NBytes, int rows, int columns);
15 void readheader(HEADER *,FILE *);
16 void writeheader(HEADER *,FILE *);
17
18
19 int main(int argc,char *argv[])
20 {
21
22 short ****datatable;
23
24 int i,j;
25 HEADER header;
26
27 /*if(argc !=2){
28 printf("Cannot open the file for read\n");
29 }*/
30
31
32 FILE *fp1=fopen(argv[1],"r");
33 FILE *fp2=fopen("newdata.dat","w");
34
35 printf("The processing file is %s \n",argv[1]);
36
37
38 datatable = (short ****)Allocate2D(sizeof(short **),2,2);
39
40 for (i=0;i<2;i++){
41 for(j=0; j<2; j++){
42 datatable[i][j] = (short **)Allocate2D(sizeof(short),2,3);
43 }
44 }
45
46 readheader(&header,fp1);
47
48 for(i=0; i<2 ;i++){
49 for (j=0; j<4; j++)fread(&datatable[i][j][0][0],sizeof(short),6,fp1);
50 }
51 fclose( fp1 );
52
53 if ( fclose( fp1 ) == 0 ) 54 { printf("Success to close input file\n");
55 }
56
57
58 /* sprintf(error_msg,"File1 Error '%s'\n",argv[1]);
59 perror( error_msg );
60 exit(1);*/
61
62 writeheader(&header,fp2);
63
64 printf("Can we get here?\n");
65
66 for(i=0; i<2 ;i++){
67 for (j=0; j<4; j++)fwrite(&datatable[i][j][0][0],sizeof(short),6,fp2);
68 fclose(fp2);
69 }
70
71 if(ferror(fp2)) {
72 printf("File2 Error\n");
73 exit(1);
74 }
75 if ( fclose( fp2 ) == 0 )
76 { printf("Success to close output file\n");
77 }
78 return(0);
79 }
80
81 void readheader(HEADER *header,FILE *fp1)
82 {
83 printf("Here is the readheader function\n");
84 fread(&(header->num1),sizeof(int),1,fp1);
85 fread(&(header->num2),sizeof(header->num2),1,fp1);
86 fread(&(header->num3),sizeof(int),1,fp1);
87 fread(&(header->num4),sizeof(int),1,fp1);
88 }
89
90 void writeheader(HEADER *header,FILE *fp2)
91 {
92 printf("Here is the writeheader function\n");
93 fwrite(&(header->num1),sizeof(int),1,fp2);
94 fwrite(&(header->num2),sizeof(header->num2),1,fp2);
95 fwrite(&(header->num3),sizeof(header->num3),1,fp2);
96 fwrite(&(header->num4),sizeof(header->num4),1,fp2);
97 }
98
99
100 void **Allocate2D(long int NBytes, int rows, int columns)
101 {
102 void **pntr;
103 int i;

104
105 pntr = (void **)malloc(sizeof(void *)*rows);
106 pntr[0] = (void *)malloc(NBytes*rows*columns);
107 for(i=1; i<rows; i++)pntr[i] = pntr[i-1]+(columns*NBytes);
108 return pntr;
109 }

ErV 07-27-2008 10:34 PM

Quote:

short ****datatable;
You are allocating memory incorrectly. Segfault happens because short** is larger (2x..4x, dependng on system) than short, so you can't assign allocated short** array to short**** variable - you'll easily go out of allocated memory bounds.
If you really need to construct 4D array this way, then that'll be something like this:
Code:

short**** construct_4D(int dimension1, int dimension2, int dimension3, int dimension4){
    short**** result;
    int i1, i2, i3, i4;
    result = (short****)malloc(sizeof(short***)*dimension1);
    for (i1 = 0; i1 < dimension1; i1++){
        result[i1] = (short***)malloc(sizeof(short**)*dimension2);
        for (i2 = 0; i2 < dimension2; i2++){
            result[i1][i2] = (short**)malloc(sizeof(short*)*dimension3);
            for (i3 = 0; i3 < dimension3; i3++){
                result[i1][i2][i3] = (short*)malloc(sizeof(short)*dimension4);
            }
        }       
    }
    return result;
}

But I recommend to use other techniques, since correctly freeing this monstrosity will be quite problematic:
Code:

void free_4D(short**** array, int dimension1, int dimension2, int dimension3){
    int i1, i2, i3;
    for (i1 = 0; i1 < dimension1; i1++){
        for (i2 = 0; i2 < dimension2; i2++){
            for (i3 = 0; i3 < dimension3; i3++)
                free(array[i1][i2][i3])
            free(array[i][j]);
        }       
        free(array[i]);
    }
    free(array);
}

Your best choice will be to allocate memory as single block and then access data using arithmetics.
Something like this:
Code:

struct array4d{
    int dimensions[4];
    short *data;
};

struct array4d* create_4d(int dimension1, int dimension2, int dimension3, int dimension 4){
    array4d *result;
    int dataSize;
    result = (array4d*)malloc(sizeof(array4d));
    result->dimensions[0] = dimension1;
    result->dimensions[1] = dimension2;
    result->dimensions[2] = dimesnions3;
    result->dimensions[3] = dimesnions4;
    dataSize = dimension1*dimension2*dimension3*dimensions4*sizeof(short);
    result->data = (short*)malloc(dataSize);
    return result;
}

void free_4d(struct array4d *array){
    free(array->data);
    free(array);   
}

int get_offset(struct array4d* array, int i1, int i2, int i3, int i4){
    return i4 + array->dimensions[3]*i3 + i2*array->dimensions[2]*array->dimensions[3] +
    i1 * array->dimensions[1]*array->dimensions[2]*array->dimensions[3];
}

short get_element(struct array4d* array, int i1, int i2, int i3, int i4){
    return array->data[get_offset(array, i1, i2, i3, i4)];
}

void put_element(struct array4d* array, short data, int i1, int i2, int i3, int i4){
    array->data[get_offset(array, i1, i2, i3, i4)] = data;
}

Or change the way your application works, and store data in other format, or use normal arrays, not dynamically allocated ones.

I recommend you to read some book about pointers, memory and C and read some real code examples. Also, you don't free memory in your program, which is a mistake.

jiml8 07-28-2008 02:30 PM

Indirection gone wild!:eek:

nanxy 07-28-2008 11:35 PM

what do u mean? please? :)

ErV 07-29-2008 02:23 AM

Quote:

Originally Posted by jiml8 (Post 3228990)
Indirection gone wild!:eek:

Well, nanxy wanted 4d array as "short****", so here is proper initialization for it.
I prefer OOP container classes or 1D arrays with methods to access them as N-dimensional data.

Quote:

Originally Posted by nanxy (Post 3229333)
what do u mean? please? :)

The initialization function I've provided (the one that returns short****) is what you asked for, but not exactly what you need. Most people wouldn't use such constructs (dynamically allocated N-dimensional arrays represented by pointers), because freeing memory correctly can turn into mini-nightmare. IMO, the normal approach would be to write wrapper class/struct/functions (depends on language. For C++ it'll be template class, for C it'll be struct + bunch of functions) which uses 1D array for storing values and functions to access those values as if it was N-dimensional array. See second piece of code.

I have no idea where you might get basic knowledge of using 1D array for storing N-dimensional data, how N-dimensional arrays are stored in memory, etc. I've picked that quite some time ago on old 8bit computer, I don't know which books cover that now.

nanxy 07-29-2008 03:03 PM

Sorry , but is this reference right?


#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct _HEADER {

int num1;
int num2;
int num3;
int num4;

}HEADER;


void readheader(HEADER *,FILE *);
void writeheader(HEADER *,FILE *);
short**** construct_4D(int dimension1, int dimension2, int dimension3, int dimension4);

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



int i,j;
HEADER header;
short ****datatable;

datatable = (short ****)construct_4D(2,2,3,4);

/*if(argc !=2){
printf("Cannot open the file for read\n");
}*/


FILE *fp1=fopen(argv[1],"r");
FILE *fp2=fopen("newdata.dat","w");

printf("The processing file is %s \n",argv[1]);

for (i=0;i<2;i++){
for(j=0; j<2; j++){
datatable[i][j] = (short **)construct_4D(2,2,3,4);
}
}



readheader(&header,fp1);

for(i=0; i<2 ;i++){
for (j=0; j<4; j++)fread(&datatable[i][j][0][0],sizeof(short),6,fp1);
}
fclose( fp1 );

if ( fclose( fp1 ) == 0 )

{
printf("Success to close input file\n");
}

writeheader(&header,fp2);

printf("Can we get here?\n");


if(ferror(fp2)) {
printf("File2 Error\n");
exit(1);
}
if ( fclose( fp2 ) == 0 )
{ printf("Success to close output file\n");
}
return(0);
}


short**** construct_4D(int dimension1, int dimension2, int dimension3, int dimension4){
short**** result;
int i1, i2, i3;
result = (short****)malloc(sizeof(short***)*dimension1);
for (i1 = 0; i1 < dimension1; i1++){
result[i1] = (short***)malloc(sizeof(short**)*dimension2);
for (i2 = 0; i2 < dimension2; i2++){
result[i1][i2] = (short**)malloc(sizeof(short*)*dimension3);
for (i3 = 0; i3 < dimension3; i3++){
result[i1][i2][i3] = (short*)malloc(sizeof(short)*dimension4);
}
}
}
return result;
}

ErV 07-29-2008 03:15 PM

Quote:

Originally Posted by nanxy (Post 3230172)
Sorry , but is this reference right?

No, it isn't because you aren't freeing memory.

Quote:

Originally Posted by nanxy (Post 3230172)
datatable[i][j] = (short **)construct_4D(2,2,3,4);

This makes no sense. construct_4D gives you fully initialized pointer to 4D array, and in this line you are obviously trying to make it 6d, making a lot memory leaks in process.

Read some books about C/memory functions.

sundialsvcs 07-30-2008 12:46 PM

Also look for existing "C" libraries designed to manage 3-D and 4-D arrays!


All times are GMT -5. The time now is 02:44 PM.