In your function int huffman(node_t *huff, int n)
you try to realloc()
the huff
pointer but in C we pass variables by value so you only receive a copy of the pointer. This means caller retains the original pointer and the realloc()
memory is lost when you return from the function. You need to pass in a **huff
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
const int expand_size = 4;
int length = 4;
typedef struct {
char w[2]; //word
int v; //value
int d; //direction
char b; //binary
} node_t;
int maxi(node_t *huff, int n) {
int maxi = huff[0].v;
for(int i=0;i<n;i++)
if(huff[i].v>maxi)
maxi=huff[i].v;
return maxi;
}
int mini(node_t *huff, int n) {
int mini = maxi(huff, n);
int w=0;
for(int i=0;i<n;i++)
if(huff[i].v<=mini && huff[i].v >=0){
w=i;
mini=huff[i].v;
}
return w;
}
int huffman(node_t **huff, int n){
int j=1;
int i=1;
while (i!=n){
int index1=mini(*huff, n);
int value1=(*huff)[index1].v;
(*huff)[index1].v=-1;
int index2=mini(*huff, n);
int value2=(*huff)[index2].v;
(*huff)[index2].v=-1;
(*huff)[index1].d = n;
(*huff)[index2].d = n;
(*huff)[index1].b = '1';
(*huff)[index2].b = '0';
if ( n == length ){
node_t *temp = realloc(*huff, (length + expand_size) * sizeof *temp);
if(!temp) {
printf("realloc failed\n");
exit(1);
}
*huff=temp;
for ( int h = length; h < length + expand_size; h++){
(*huff)[h].v = 0;
}
length += expand_size;
}
(*huff)[n].v=value1 + value2;
(*huff)[n].w[0]=j+'0';
j++;
i=i+2;
n++;
}
return n;
}
int main( int argc, char** argv) {
int opt;
char *file = NULL;
char steps = 0;
char compression_level = 0;
while ((opt = getopt (argc, argv, "o:f:v")) != -1) {
switch (opt) {
case 'f':
file = optarg;
break;
case 'v':
steps = 1;
break;
case 'o':
compression_level = atof ( optarg );
break;
case '?':
printf("Złe parametry wywołania");
return 1;
break;
}
}
if(!file) {
printf("file is required\n");
return EXIT_FAILURE;
}
FILE *read = fopen(file, "r");
node_t *huff = malloc(length * sizeof *huff);
int counter = 0;
for (int i=0; i<length; i++)
huff[i].v = 0;
if (read == NULL) {
printf ("file can't be opened \n");
return 1;
}
if(compression_level == 1){
int c;
while ((c = fgetc(read)) != EOF ){
for (int i=0; i<length; i++){
if (!huff[i].v){
huff[i].w[0] = c;
huff[i].v++;
counter++;
break;
}
if (huff[i].w[0]== c){
huff[i].v++;
break;
}
if (i == length - 1){
node_t *temp = realloc(huff, (length + expand_size) * sizeof *temp);
if(!temp) {
printf("relloc failed\n");
exit(EXIT_FAILURE);
}
huff=temp;
for (int j = length; j < length + expand_size; j++)
huff[j].v = 0;
length += expand_size;
}
}
}
}
int n = huffman(&huff, counter);
for(int i=0; i<counter; i++){
int l=i;
if(compression_level == 1)
printf("%c: ", huff[i].w[0]);
if(compression_level == 2)
printf("%c%c: ", huff[i].w[0], huff[i].w[1]);
while (l!=n-1){
printf("%c", huff[l].b);
l = huff[l].d;
}
printf("\n");
}
if (steps == 1) {
for (int i=0; i<counter; i++){
if( huff[i].w[0] == 10)
printf("'%d' 'LINE FEED' occured %d razy\n", huff[i].w[0], huff[i].v);
}
printf("array length %d\n", length);
printf("how many nodes %d\n", n);
printf("how many primary nodes %d\n", counter);
}
free(huff);
fclose(read);
return 0;
}
I also reduced scope of variables, checked return value of realloc()
, checked that file
is set. Here is the valgrind summary after the change:
==2612036== HEAP SUMMARY:
==2612036== in use at exit: 0 bytes in 0 blocks
==2612036== total heap usage: 41 allocs, 41 frees, 53,016 bytes allocated
==2612036==
==2612036== All heap blocks were freed -- no leaks are possible
5
solved Realloc not working in my program, any ideas why?