Reputation: 367
I'm trying to use a structure to hold a pointer to a data block that I change sometimes when a file is updated, the idea being to free the old data block, malloc a new one of the right size, and assign the pointer to pointer in the structure to the pointer returned by malloc, and this is how I thought I should do it. But it seg faults. In fact in the larger program that I pared down to make this test program, its not seg faulting but writing to stdout does nothing after the malloc (anywhere in the program after that). I guess I am writing over the stdout FD, the cause being that I am using the pointers incorrectly when I set the pointer to the malloc()
ed return value.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <malloc.h>
#include <inttypes.h>
struct mystruct {
int offset;
int ** d;
};
int filecheck (struct mystruct *g, int * count) {
int v, size = 0;
FILE *f = fopen("/home/pi/schedule/default", "rb");
if (f == NULL) {
return 0;
}
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
int schedsize = sizeof(int);
int elementcount = size / schedsize;
// free(*(g->d));
// seg fault next line
if ((*(g->d) = malloc(size))==NULL) return 0;
if (elementcount != fread(*(g->d), schedsize, elementcount, f)) {
free(*(g->d));
return 0;
}
fclose(f);
*count = elementcount;
return 1;
}
void setp (struct mystruct *g) {
// if uncommented, seg fault here
// *(g->d) = NULL;
}
int main (){
struct mystruct g;
setp(&g);
int i, count = 0;
if (filecheck(&g, &count)==0) {
printf("Returned 0\n");
return 0;
}
while (1) {
printf("%d\n", (*(g.d))[i]);
sleep(1);
}
return 0;
}
For convenience I want to set mystruct.d
to NULL
initially, in setp()
, but even if thats comented out the code still fails, so I know its completely wrong. Maybe I don't need to be using a pointer to pointer but it seems to me I do.
EDIT: Modified as per answer, is this OK?
struct mystruct {
int offset;
int * d;
};
int filecheck (struct mystruct *g, int * count) {
int v, size = 0;
FILE *f = fopen("/home/pi/schedule/default", "rb");
if (f == NULL) {
return 0;
}
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
int schedsize = sizeof(int);
int elementcount = size / schedsize;
free (g->d);
if ((g->d = malloc(size))==NULL) return 0;
if (elementcount != fread(g->d, schedsize, elementcount, f)) {
free(g->d);
return 0;
}
fclose(f);
*count = elementcount;
return 1;
}
void setp (struct mystruct *g) {
g->d = NULL;
}
int main (){
struct mystruct g;
setp(&g);
int i, count = 0;
if (filecheck(&g, &count)==0) {
printf("Returned 0\n");
return 0;
}
while (1) {
for (i=0;i<count;i++) {
printf("%d %d \n", *((g.d)+i), g.d[i]);
}
sleep(1);
}
return 0;
}
This seems to work but is it correct or am I writing over some part of memory I am not supposed to again with this?
Upvotes: 0
Views: 282
Reputation: 134286
You need to allocate memory to all the pointer elements before using them.
Here, d
being a pointer to pointer, first you need to allocate memory for d
itself, then you should go on for dereferencing d
(using *d
).
For example, either
void setp (struct mystruct *g) {
g->d = NULL; // no need to derererence d here, but later need to allocate
}
or, (for better)
void setp (struct mystruct *g) {
g->d = malloc(32 * sizeof (int *)); // d is allocated
g->d[i] = malloc(16 * sizeof (int)); // or g->d[i] = NULL; or *(g->d) = NULL;
}
should work fine.
Also, the recommended siganture of main()
is int main(void)
.
Upvotes: 2