realloc() works only a few times [duplicate] - c

My C program is crashing and I am too new to figure it out. It's very simple so far and I imagine the code is enough to figure out what is going wrong.
I am simply trying to read a file line by line. I will double the memory of a structure once I am out of memory. If this is not enough information, I will give whatever else you need.
Thank you very much for any help, as I have been stuck for hours now.
/*
John Maynard
1000916794
7/15/2013
HW-06
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
struct course
{
char subject[11];
int catalogNum;
int sectionNum;
int enrollmentTotal;
int enrollmentCap;
};
void readFile(struct course *d, char* filename);
void double_array_size(struct course *d, int new_size);
int main(void)
{
char *filename = "hw06-data.csv";
struct course *d;
d = malloc( N * sizeof(struct course));
readFile(d, filename);
}
void readFile(struct course *d, char* filename)
{
FILE* fp;
char buffer[100];
int i = 0, array_size = 100;
struct course *temp;
if( ( fp = fopen(filename, "r") ) == NULL)
{
printf("Unabale to open %s.\n", filename);
exit(1);
}
fgets(buffer, sizeof(buffer), fp);
while( fgets(buffer, sizeof(buffer), fp) != NULL)
{
if (i == array_size)
{
array_size *= 2;
double_array_size(d, array_size);
printf("reached limit...increasing array to %d structures\n", array_size);
}
i++;
}
fclose( fp );
}
void double_array_size(struct course *d, int new_size)
{
struct course *temp;
temp = realloc(d, new_size * sizeof(struct course));
if(temp == NULL)
{
printf("unable to reallocate\n");
exit(1);
}
else
d = temp;
}

realloc() may return a different pointer than the original one but you assign that to temp only so the calling function still works with the original pointer afterwards. Change double_array_size() to return the new pointer returned by realloc() and call
d = double_array_size(d, array_size);
Furthermore you should always check the result fo malloc(), realloc() etc. They may return NULL if there is no more memory available

Combining Ingo's and codroipo's answers, you have to either return the new pointer from double_array_size, or you have to pass in a pointer to d so you can update the pointer from double_array_size

Realloc reallocates memory, so probably memory pointed by d will be released, so double_array_size has to edit d, you could try:
void double_array_size(struct course** d, int new_size){
*d = realloc(*d, new_size * sizeof(struct course));
.
.
.
}

Related

Using an array of structures with call by reference

Here is my problem: I have to make this program for school and I spent the last hour debugging and googling and haven't found an answer.
I have an array of structures in my main and I want to give that array to my function seteverythingup (by call by reference) because in this function a string I read from a file is split up, and I want to write it into the structure but I always get a SIGSEV error when strcpy with the struct array.
This is my main:
int main(int argc, char *argv[])
{
FILE* datei;
int size = 10;
int used = 0;
char line[1000];
struct raeume *arr = (raeume *) malloc(size * sizeof(raeume*));
if(arr == NULL){
return 0;
}
if(argc < 2){
return 0;
}
datei = fopen(argv[1], "rt");
if(datei == NULL){
return 0;
}
fgets(line,sizeof(line),datei);
while(fgets(line,sizeof(line),datei)){
int l = strlen(line);
if(line[l-1] == '\n'){
line[l-1] = '\0';
}
seteverythingup(&line,arr,size,&used);
}
ausgabeunsortiert(arr,size);
fclose(datei);
return 0;
}
and this is my function:
void seteverythingup(char line[],struct raeume *arr[], int size,int used)
{
char *token,raumnummer[5],klasse[6];
int tische = 0;
const char c[2] = ";";
int i=0;
token = strtok(line, c);
strcpy(raumnummer,token);
while(token != NULL )
{
token = strtok(NULL, c);
if(i==0){
strcpy(klasse,token);
}else if(i==1){
sscanf(token,"%d",&tische);
}
i++;
}
managesize(&arr[size],&size,used);
strcpy(arr[used]->number,raumnummer);
strcpy(arr[used]->klasse,klasse);
arr[used]->tische = tische;
used++;
}
Edit: Since there is more confusion I wrote a short program that works out the part you are having trouble with.
#include <cstdlib>
struct raeume {
int foo;
int bar;
};
void seteverythingup(struct raeume *arr, size_t len) {
for (size_t i = 0; i < len; ++i) {
arr[i].foo = 42;
arr[i].bar = 53;
}
}
int main() {
const size_t size = 10;
struct raeume *arr = (struct raeume*) malloc(size * sizeof(struct raeume));
seteverythingup(arr, size);
return 0;
}
So basically the signature of your functions is somewhat odd. Malloc returns you a pointer to a memory location. So you really dont need a pointer to an array. Just pass the function the pointer you got from malloc and the function will be able to manipulate that region.
Original Answer:
malloc(size * sizeof(raeume*));
This is probably the part of the code that gives you a hard time. sizeof returns the size of a type. You ask sizeof how many bytes a pointer to you raeume struct requires. what you probably wanted to do is ask for the size of the struct itself and allocate size times space for that. So the correct call to malloc would be:
malloc(size * sizeof(struct raeume));

Passing pointer of pointers to function, returning both an int and an address (by parameter)

I've got a function which, as is, works correctly. However the rest of the program has a limitation in that I've preset the size of the array (the space to be allocated). Obviously, this is problematic should an event arise in which I need extra space for that array. So I want to add dynamic allocation of memory into my program.
But I'm having an issue with the whole pointer to a pointer concept, and I've utterly failed to find an online explanation that makes sense to me...
I think I'll want to use malloc(iRead + 1) to get an array of the right size, but I'm not sure what that should be assigned to... *array? **array? I'm not at all sure.
And I'm also not clear on my while loops. &array[iRead] will no longer work, and I'm not sure how to get a hold of the elements in the array when there's a pointer to a pointer involved.
Can anyone point (heh pointer pun) me in the right direction?
I can think of the following approaches.
First approach
Make two passes through the file.
In the first pass, read the numbers and discard them but keep counting the number of items.
Allocate memory once for all the items.
Rewind the file and make a second pass through it. In the second pass, read and store the numbers.
int getNumberOfItems(FILE* fp, int hexi)
{
int numItems = 0;
int number;
char const* format = (hexi == 0) ? "%X" : "%d";
while (fscanf(fp, format, &number) > 0) {
++numItems;
return numItems;
}
void read(int *array, FILE* fp, int numItems, int hexi)
{
int i = 0;
char const* format = (hexi == 0) ? "%X" : "%d";
for ( i = 0; i < numItems; ++i )
fscanf(fp, format, &array[i]);
}
int main(int argc, char** argv)
{
int hexi = 0;
FILE* fp = fopen(argv[1], "r");
// if ( fp == NULL )
// Add error checking code
// Get the number of items in the file.
int numItems = getNumberOfItems(fp, hexi);
// Allocate memory for the items.
int* array = malloc(sizeof(int)*numItems);
// Rewind the file before reading the data
frewind(fp);
// Read the data.
read(array, fp, numItems, hexi);
// Use the data
// ...
// ...
// Dealloate memory
free(array);
}
Second approach.
Keep reading numbers from the file.
Every time you read a number, use realloc to allocate space the additional item.
Store the in the reallocated memory.
int read(int **array, char* fpin, int hexi)
{
int number;
int iRead = 0;
// Local variable for ease of use.
int* arr = NULL;
char const* format = (hexi == 0) ? "%X" : "%d";
FILE *fp = fopen(fpin, "r");
if (NULL == fp){
printf("File open error!\n");
exit(-1);
}
while (fscanf(fp, format, &number) > 0) {
arr = realloc(arr, sizeof(int)*(iRead+1));
arr[iRead] = number;
iRead += 1;
}
fclose(fp);
// Return the array in the output argument.
*array = arr;
return iRead;
}
int main(int argc, char** argv)
{
int hexi = 0;
int* array = NULL;
// Read the data.
int numItems = read(&array, argv[1], hexi);
// Use the data
// ...
// ...
// Dealloate memory
free(array);
}
int read(int **array, char* fpin, int hexi) {
int iRead = 0;
int i, *ary;
char *para;
FILE *fp;
fp = fopen(fpin, "r");
if (NULL == fp){
printf("File open error!\n");
exit(-1);
}
para = (hexi == 0) ? "%*X" : "%*d";
while (fscanf(fp, para)!= EOF)
++iRead;
ary = *array = malloc(iRead*sizeof(int));
if(ary == NULL){
printf("malloc error!\n");
exit(-2);
}
rewind(fp);
para = (hexi == 0) ? "%X" : "%d";
for(i = 0; i < iRead; ++i)
fscanf(fp, para, &ary[i]);
fclose(fp);
return iRead;
}
I'd suggest something like this:
int read(int **array_pp, char* fpin, int hexi) {
...
int *array = malloc (sizeof (int) * n);
for (int i=0; i < n; i++)
fscanf(fp, "%X",&array[i]);
...
*array_pp = array;
return n;
}
Notes:
1) You must use "**" if you want to return a pointer in a function argument
2) If you prefer, however, you can declare two pointer variables (array_pp and array) to simplify your code.
I think you wouldn't call it an array. Arrays are of fixed size and lie on the stack. What you need (as you already said), is dynamically allocated memory on the heap.
maybe that's why you didn't find much :)
here are some tutorials:
http://en.wikibooks.org/wiki/C_Programming/Arrays (and following pages)
http://www.eskimo.com/~scs/cclass/int/sx8.html
you got the function declaration correctly:
int read(int **array, char* fpin, int hexi)
What you need to do:
find out how much memory you need, eg. how many elements
allocate it with *array = malloc(numElements * sizeof(int)) (read "at the address pointed by array allocate memory for numElements ints")
now you can (*array)[idx] = some int (read "at the address pointed by array, take the element with index idx and assign some int to it")
call it with int* destination; int size = read(&destination, "asdf", hexi)
hope it helps..

Memory allocation of 3-d arrays for reading pixel data of images using libjpeg

I am trying to copy the pixel data of an image to a matrix using libjpeg. Something is going wrong with the pointers. Please help.
The problem in brief: I pass an int ***p pointer to a function which reads pixel data. Within the function, I am able to access the elements p[i][j][k] and perform operations on them but when I try to do the same in main the program crashes.
The main function is:
#include<stdio.h>
#include<stdlib.h>
#include<jpeglib.h>
#include"functions.h"
void main(void)
{
char * file="a.jpg";
int ***p; // to store the pixel values
int s[2]={0,0}; // to store the dimensions of the image
read_JPEG_file(file,p,s); // Function that reads the image
printf("%d",p[0][0][0]); // This makes the program crash
}
The file functions.h reads:
int read_JPEG_file(char * file, int ***p, int **s)
{
int i,j;
//-----------------libjpeg procedure which I got from the documentation------------
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err=jpeg_std_error(&jerr);
FILE * infile; /* source file */
JSAMPARRAY buffer; /* Output row buffer */
int row_stride;
if ((infile = fopen(filename, "rb")) == NULL)
{
fprintf(stderr, "can't open %s\n", filename);
return 0;
}
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
row_stride = cinfo.output_width * cinfo.output_components;
buffer=(*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
s[0]=cinfo.output_height;
s[1]=cinfo.output_width;
p=(int ***)malloc(s[0]*sizeof(int **));
for (i=0;i<s[0];i++)
{
p[i]=(int **)malloc(s[1]*sizeof(int *));
for (j=0;j<s[1];j++)
{
p[i][j]=(int *)malloc(3*sizeof(int));
}
}
while (cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines(&cinfo, buffer, 1);
for ( i=0; i<cinfo.output_width; i++)
{
p[cinfo.output_scanline-1][i][0]=(int)buffer[0][0+3*i];
p[cinfo.output_scanline-1][i][1]=(int)buffer[0][1+3*i];
p[cinfo.output_scanline-1][i][2]=(int)buffer[0][2+3*i];
}
}
printf("%d",p[0][0][0]); // This works just fine
return 0;
}
I know that something is wrong with the memory allocation but I don't know what. I tried another test program and successfully allocated a memory block 500X500X500 integers long, and it was working-it was outputting random integers without crashing- so lack of memory is not a problem.
Your int ***p isn't malloc.
When you send him to read_JPEG_file a second variable int ***p was created.
This second variable was destruct at the end of read_JPEG_file. So you can use p
in read_JPEG_file but that's all.
There is three way to solve it.
The first and I think the easier to understand is to return p.
int ***read_JPEG_file(char * file, int ***p, int **s) {
...
return p;
}
int main() {
...
p = read_JPEG_file(file, p, s);
}
(It became unnecessary to send p)
The second way is to malloc p in the main and then to send him.
It seems a bit hard to do in your case.
The third is to send the address of p in the main. You will have a (int * * * *p).
You have to take care when you use it.
You can do something like that :
int read_JPEG_file(char * file, int ****p, int **s)
{
...
*p=(int ***)malloc(s[0]*sizeof(int **));
}
Now you have to use *p instead of p.
*p mean the value that contain the pointer p. p is an int * * * * so his value is the int * * *.
int main()
{
...
read_JPEG_file(file, &p, s);
}

realloc structure with function in C

My C program is crashing and I am too new to figure it out. It's very simple so far and I imagine the code is enough to figure out what is going wrong.
I am simply trying to read a file line by line. I will double the memory of a structure once I am out of memory. If this is not enough information, I will give whatever else you need.
Thank you very much for any help, as I have been stuck for hours now.
/*
John Maynard
1000916794
7/15/2013
HW-06
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
struct course
{
char subject[11];
int catalogNum;
int sectionNum;
int enrollmentTotal;
int enrollmentCap;
};
void readFile(struct course *d, char* filename);
void double_array_size(struct course *d, int new_size);
int main(void)
{
char *filename = "hw06-data.csv";
struct course *d;
d = malloc( N * sizeof(struct course));
readFile(d, filename);
}
void readFile(struct course *d, char* filename)
{
FILE* fp;
char buffer[100];
int i = 0, array_size = 100;
struct course *temp;
if( ( fp = fopen(filename, "r") ) == NULL)
{
printf("Unabale to open %s.\n", filename);
exit(1);
}
fgets(buffer, sizeof(buffer), fp);
while( fgets(buffer, sizeof(buffer), fp) != NULL)
{
if (i == array_size)
{
array_size *= 2;
double_array_size(d, array_size);
printf("reached limit...increasing array to %d structures\n", array_size);
}
i++;
}
fclose( fp );
}
void double_array_size(struct course *d, int new_size)
{
struct course *temp;
temp = realloc(d, new_size * sizeof(struct course));
if(temp == NULL)
{
printf("unable to reallocate\n");
exit(1);
}
else
d = temp;
}
realloc() may return a different pointer than the original one but you assign that to temp only so the calling function still works with the original pointer afterwards. Change double_array_size() to return the new pointer returned by realloc() and call
d = double_array_size(d, array_size);
Furthermore you should always check the result fo malloc(), realloc() etc. They may return NULL if there is no more memory available
Combining Ingo's and codroipo's answers, you have to either return the new pointer from double_array_size, or you have to pass in a pointer to d so you can update the pointer from double_array_size
Realloc reallocates memory, so probably memory pointed by d will be released, so double_array_size has to edit d, you could try:
void double_array_size(struct course** d, int new_size){
*d = realloc(*d, new_size * sizeof(struct course));
.
.
.
}

Constant pointer array with struct fields that may point to malloc allocated fields?

int main() {
Employee *array[SIZE]; //Employee is a typedef struct --includes char *name, DATE *dateOfBirth, DATE is also a typedef struct, has 3 int fields month, day, year,`
fillArray(array, &count, fpin1, fpin2);
freeMemory(array, int count);
}
fillArray(Employee *array[], int *count, FILE *fpin1, FILE *fpin2)
char buffer[MAX], buffer2[MAX];
while (fgets(buffer, MAX, fpin1) != NULL && fgets(buffer2, MAX, fpin2) != NULL){
array[*count]->name = (char *) malloc(sizeof(char)*25);
assert(array[*count]->name != NULL);
strncpy(array[*count]->name, buffer, 15);
strncpy(buffer2, temp, 2);
array[*count]->dateOfBirth->day = atoi(temp)
}
The code compiles but keeps failing with segmentation fault, it seems to fail at my fgets? or my malloc, what am I doing wrong? I really can't seem to figure that out.
Also how would you go about freeing this memory in a
freeMemory(Employee *array[], int count)
function?
Should be:
int main() {
Employee array[SIZE]; //Employee is a typedef struct --includes char *name, DATE *dateOfBirth, DATE is also a typedef struct, has 3 int fields month, day, year,`
fillArray(&array, &count, fpin1, fpin2);
freeMemory(&array, int count);
}
You aren't allocating your Employee objects anywhere, so array[0] points to some random address.
Employee* array[SIZE];
This is an array that stores pointers to Employee structs.
I think you mean
fillArray(Employee* array[], int* count, FILE *fpin1, FILE *fpin2)
{
char buffer[MAX], buffer2[MAX];
int i = 0;
while ( fgets(buffer, MAX, fpin1) != NULL &&
fgets(buffer2, MAX, fpin2) != NULL )
{
// the array does not hold any valid memory address.
array[i] = malloc( sizeof(Employee) );
assert( array[i] != NULL );
// now on the new employee add some char memory
(array[i])->name = malloc( sizeof(char) * 25 );
assert(array[i]->name != NULL);
strncpy(array[i]->name, buffer, 15);
strncpy(buffer2, temp, 2);
array[i]->dateOfBirth->day = atoi(temp)
++i;
(*count)++;
}
}
doing array[*count] besides looking weird, always modifies the same index. You never modified *count anywhere.
This code does not check that you do not exceed the bounds of the array passed.
Also : for the freeMemory()
freeMemory(Employee* array[], int count)
{
int i = 0;
while( i < count )
{
free(array[i]);
array[i] = NULL;
++i;
}
}

Resources