-4

Happy New Year!

I have been struggling to find what causes the error I will explain below for some time now and I would be so very grateful for any help. I have the following code which, in principle, should implement a stack:

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

void resize(int *nmax, int *d){
    int i, *u;
    *nmax *= 2;
    u = (int *)realloc(d,sizeof(int)*(*nmax));
    if(u == NULL){
        printf("Error!\n");
        exit(1);
    }
    d = u;
}

void push(int *n, int *d, int *nmax){
    int u = *n , i;
    if(u == *nmax) {
        resize(nmax, d);
    }
    *(d + u) = u;
    u++;
    *n = u;
}

void pop(int *n){
    int u = *n;
    *n = u - 1;
}

int main(){
    int *d, n = 0, i, nmax = 5;
    d = (int *)malloc(sizeof(int)*nmax);
    *(d+(n))= n;
    n++;
    *(d+(n)) = n;
    n++;
    *(d+(n)) = n;
    n++;
    //for(i = 0;i < n;i++)
        //printf("%d\n",*(d+i));
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    push(&n,d, &nmax);
    //pop(&n);
    //pop(&n);
    //pop(&n);
    for(i = 0;i<n;i++)
        printf("%d\n",*(d+i));

    return 0;
}

It seems to behave normally until I un-comment the printf statement before the stack of push operations. The error I get is:

0
1
2
*** Error in `./a.out': realloc(): invalid next size: 0x0000000000f08010 ***

I am not sure I have explained it ok and if I didn't please let me know of any additional details I could add so as to make it more clear.

Thank you very much for your help!

EDIT:

With the hope that the code has now become a little more readable, this is what I have:

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

void resize(int *sizeOfArray, int *myArray){
    int i, *u;
    *sizeOfArray *= 2;
    u = (int *)realloc(myArray,sizeof(int)*(*sizeOfArray));
    if(u == NULL){
        printf("Error!\n");
        exit(1);
    }
    myArray = u;
}

void push(int *pos, int *myArray, int *sizeOfArray){
    int i;
    if(*pos == *sizeOfArray) {
        resize(sizeOfArray, myArray);
    }
    *(myArray + (*pos)) = *pos;
    (*pos)++;
}

void pop(int *pos){
    (*pos)--;
}

int main(){
    int *myArray, pos = 0, i, sizeOfArray = 5;
    myArray = (int *)malloc(sizeof(int)*sizeOfArray);
    *(myArray + pos)= pos;
    pos++;
    *(myArray + pos) = pos;
    pos++;
    *(myArray + pos) = pos;
    pos++;
    //for(i = 0;i < pos;i++)
        //printf("%d\n",*(myArray+i));
    push(&pos, myArray, &sizeOfArray);
    push(&pos, myArray, &sizeOfArray);
    push(&pos, myArray, &sizeOfArray);
    push(&pos, myArray, &sizeOfArray);
    //pop(&pos);
    //pop(&pos);
    //pop(&pos);
    for(i = 0;i<pos;i++)
        printf("** %d\n",*(myArray+i));

    return 0;
}

Now, the error has changed - which, perhaps, is an indication that there is something wrong with the approach - and it reads:

I should get:

** 0
** 1
** 2
** 3
** 4
** 5
** 6

Instead, I get:

** 0
** 0
** 2
** 3
** 4
** 5
** 6

Why? I only get this when I un-comment the printf in the middle.

Thank you for your help.

moijoune
  • 21
  • 1
  • 8
  • 3
    `d = u;` only changes the local value that was passed to `resize` which is then forgotten. – Weather Vane Jan 03 '18 at 13:27
  • 1
    A stack of what? This code is very unclear because of the meaningless identifiers. What the heck do `d`, `n`, `u`, `nmax` stand for? You've also made things much more complicated (and hard to follow) than necessary; for example with all those explicit array index calculations. Why? – meaning-matters Jan 03 '18 at 13:33
  • @WeatherVane Thank you very much for your help! However, I am getting a 'normal' behavior (at least, I see what I anticipate I should see) if I am not "printf-ing" before the push operations. Shouldn't I get a wrong result most of the time if your suggestion was what was going on? – moijoune Jan 03 '18 at 14:05
  • @meaning-matters Thank you very much for your comment. A stack of nothing. It is an exercise I put myself. I changed all the d, n, u, nmax so they reflect somehow what I wanted them to be. I hope the code improved readability-wise. Anyway, I take the point you are making. – moijoune Jan 03 '18 at 14:08
  • @Jean-FrançoisFabre Thank you! – moijoune Jan 03 '18 at 14:09
  • @moijoune it is a classic sympton of undefined behaviour when adding or removing statements makes it "seem to work". Undefined behaviour may or may not cause a crash. If it was certain then it would be defined! – Weather Vane Jan 03 '18 at 14:43

1 Answers1

-1

int *myArray is locale to your function, the statement myArray = u; will only change the locale value, not the value of calling function.

You must use double pointer or return the value.

int *resize(int *sizeOfArray, int *myArray){
    *sizeOfArray *= 2;
    int *u = realloc(myArray, *sizeOfArray * sizeof *myArray);
    if (u == NULL) {
        printf("Error!\n");
        exit(1);
    }
    return u;
}

myArray = resize(sizeOfArray, myArray);

Of course, you must change for this behavior in your push() too.

Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • Thank you so much! Do you mean that I should also make int* push(...)? – moijoune Jan 03 '18 at 14:15
  • 1
    @moijoune yes, you are in essence wrapping `realloc`, so behave like `realloc`. – Pablo Jan 03 '18 at 14:16
  • I think that it's bad idea when a function fails to call `exit` right away. When a call fails it doesn't mean that the whole process should end. Just return an error value (`NULL` in this case) and let the user decide what to do. – Pablo Jan 03 '18 at 14:18
  • @Pablo ΤΗΑΝΚ YOU SO MUCH!!! Yes, this is what solved the problem. I still feel a little bemused that the printf in the middle was causing all of this but, perhaps, that was accidental. I am not sure why the array wasn't passed by reference which means more reading. Thank you so much again! – moijoune Jan 03 '18 at 14:23
  • @moijoune it was causing trouble because it was accessing memory that was invalid at the time. In your implementation `realloc` might've returned a different pointer, thus making the original one invalid. Accessing such an invalid pointer yields undefined behaviour, for example it could print some numbers but it also can crash. **Beacause** your implementation throw away the new pointer and you kept the old one, this undefined behaviour happened and in your case it lead into a crash with your first version and with garbage with the second version. – Pablo Jan 03 '18 at 14:38
  • @Pablo Thank you very much. I suppose that this will escalate my situation much further :) but Ι honestly thought that I was passing the real myArray by reference. Thus, I was wrongly anticipating that the reallocation would affect the original array. But you are absolutely correct that I was getting garbage one way or another. Thank you! – moijoune Jan 03 '18 at 14:47
  • @moijoune: *I am not sure why the array wasn't passed by reference which means more reading.* because in C there is not such thing as *pass by reference*, it's always by value. With pointers you simulate the *by reference*. Bah, I was writing an long answer and the thread has been closed, so I cannot post it anymore. It was a rather long answer. If you are interested in my answer: https://pastebin.com/t5tmX5U2 – Pablo Jan 03 '18 at 15:24
  • @Pablo I so appreciate your help! You are wonderful and THANK YOU SO MUCH! I am now getting an idea of my profound misconceptions. I can't thank you enough! – moijoune Jan 03 '18 at 15:37