0

I'm having trouble writing and reading a stack (linked list of nodes) on a file, as the writing and the reading, comes in different sizes.

When it comes to the writing, this is my function:

int my_stack_write(struct my_stack *stack, char *filename){
        int count = 0;
        struct my_stack_node *aux =malloc(sizeof(struct my_stack_node));
        FILE *file = fopen(filename, "wb");

        if(stack->first != NULL){
                aux = stack->first;
                count++;
                while(aux->next != NULL){
                        printf("New node in s1: (%p)\n", aux->data);
                        fwrite(aux ,sizeof(struct my_stack_node), 1, file);
                        aux = aux->next;
                        count++;
                }
                printf("New node in s1: (%p)\n", aux->data);
                fwrite(aux ,sizeof(struct my_stack_node), 1, file);

        }
        fclose(file);
        return count;
}

And this is my read:

struct my_stack *my_stack_read(char *filename){
        struct my_stack *stackRead = my_stack_init(sizeof(struct my_stack_node));;
        struct my_stack_node *stackNode = malloc(sizeof(struct my_stack_node));
        FILE *file = fopen(filename, "rb");

        if(!file){
                puts("Impossible obrir el fitxer");
                return NULL;
        }else{

                while(fread(stackNode, sizeof(struct my_stack_node), 1, file)){

                                printf("New node in fs1: (%p)\n", stackNode->data);
                                stackNode = (struct my_stack_node*) stackNode;
                                my_stack_push(stackRead, stackNode);
                }
                fclose(file);
                return stackRead;
        }
}

The test I am using is this one:

 if (my_stack_write(s1, "/tmp/my_stack.data") != len1) {
        puts("Error in my_stack_write (s1)");
        exit(1);
    }
    puts("\nReading the file...");
    fs1 = my_stack_read("/tmp/my_stack.data");
    if (!fs1) {
        puts("Error in my_stack_read (fs1)");
        exit(1);
    }

    if (my_stack_len(s1) != my_stack_len(fs1)) {
    printf("Stacks s1 (initial stack 1) %d and fs1 %d (retrieved from file) don't have the same length\n",my_stack_len(s1) ,my_stack_len(fs1));

        exit(1);
    }
puts("s1 and the one retrieved from file (fs1) have the same length.");
puts("Comparing the data...");

// Test we can free the data and compare stacks s1 and fs1
while ((data1 = my_stack_pop(s1))) {
    data2 = my_stack_pop(fs1);
    printf("Node of s1: (%d, %s)\t", data1->val, data1->name);
    printf("Node of fs1: (%d, %s)\n", data2->val, data2->name);
    if (!data2 || data1->val != data2->val || my_strcmp(data1->name, data2->name)) {
        printf("Data in s1 and fs1 are not the same.\n (data1->val: %d <> data2->val: %d) o (data1->name: %s <> data2->name: "
               "%s)\n",
               data1->val, data2->val, data1->name, data2->name);
        exit(1);
    }
    size1 = sizeof(*data1);
    size2 = sizeof(*data2);
    free(data1);
    free(data2);
}
printf("size of data from s1: %d\t", size1);
printf("size of data from fs1: %d\n", size2);

Just changed the test, and managed to read "better", the output is:

Writting the smaller stack (s1), it must truncate the file.
New node in s1: (0x55969ed2be70)
New node in s1: (0x55969ed2be00)
New node in s1: (0x55969ed2bd90)
New node in s1: (0x55969ed2bd20)
New node in s1: (0x55969ed2bcb0)
New node in s1: (0x55969ed2bc40)
New node in s1: (0x55969ed2bbd0)
New node in s1: (0x55969ed2bb60)
New node in s1: (0x55969ed2baf0)
New node in s1: (0x55969ed2ba80)

Reading the file...
New node in fs1: (0x55969ed2be70)
New node in fs1: (0x55969ed2be00)
New node in fs1: (0x55969ed2bd90)
New node in fs1: (0x55969ed2bd20)
New node in fs1: (0x55969ed2bcb0)
New node in fs1: (0x55969ed2bc40)
New node in fs1: (0x55969ed2bbd0)
New node in fs1: (0x55969ed2bb60)
New node in fs1: (0x55969ed2baf0)
New node in fs1: (0x55969ed2ba80)
s1 and the one retrieved from file (fs1) have the same length.

So I think the read and the write, write and read the exact same node every time, but when i compares the nodes:

Comparing the data...
Node of s1: (-1630355856, �U)   Node of fs1: (-1630350448, �U)
Data in s1 and fs1 are not the same.
 (data1->val: -1630355856 <> data2->val: -1630350448) o (data1->name: �U <> data2->name: �U)

it "explodes". Any idea why is it?

Any help will work.

flaixman
  • 702
  • 6
  • 14
  • [while(!feof(fp)) is always wrong](https://stackoverflow.com/questions/5431941) – user3386109 Jan 02 '19 at 21:21
  • what's the right way to have the same stack I just wrote? How do I modify it? – flaixman Jan 02 '19 at 21:22
  • A lot of code is missing so it's not easy to help you. But it seems that you are writing pointer values to the file. That is nearly always a mistake. – Support Ukraine Jan 02 '19 at 21:22
  • 1
    Oh, you can't write pointers out and expect to read the addresses back and have them point to anything meaningful... (e.g. `fwrite(aux ,sizeof(aux), 1, file);`) You have to *serialize* your data and write the actual data to a file, and then read the values back into your struct and stack (which both will have very different addresses when read back in) `aux` is a pointer, and `sizeof (aux)` is `sizeof a_pointer`. – David C. Rankin Jan 02 '19 at 21:22
  • 2
    The final `fwrite` in your write function is incorrect. You are writing the _pointer_ to the stack struct and _not_ the stack struct itself--not terribly useful. You [probably] want `fwrite(stack, sizeof(struct my_stack), 1, file);`. And, you probably want to move this to the top and write it out _first_ because you read it first in your read function. Also, `fread(stackRead, sizeof(stackRead), 1, file);` is incorrect. You want: `fread(stackRead, sizeof(sizeof(struct mystack)), 1, file);` – Craig Estey Jan 02 '19 at 21:24
  • At first glance, it seems that your writing logic is writing the list as a sequence of `my_stack_node` type instances, while the reading logic, initially reads an instance of type `struct my_stack` and then reads the rest of the list as instances of type `struct my_stack_node`. If both types are not binary-equivalent, this will surely produce wrong results. – BlueStrat Jan 02 '19 at 21:26
  • @flaixman That was just the first thing that I saw. It's a common problem, so I thought you should be aware of it. – user3386109 Jan 02 '19 at 21:26
  • In the read function it seems you `malloc` into `stackRead` twice and thereby leaks memory – Support Ukraine Jan 02 '19 at 21:30
  • I will try for a print debugging, as I only have 10 nodes for the text, I will print each node I write, and then each node I read. I'll catch back once I have tried all your solutions. Thanks. – flaixman Jan 02 '19 at 21:43
  • @3422102 I just changed the code for a clear view (the data type is void, but it correlates). Can you see anything more? Tried some things, but with no avail – flaixman Jan 02 '19 at 22:07

0 Answers0