-1

This compiles fine in x86, but when I used it in x64 configuration the x and y variables do not have an address when I try to access them? Do need some sort of padding to align to a larger address? Using MSVC..

#define ARR_SIZE 25

typedef struct {
    unsigned int x;
    unsigned int y;
}Stuff;

void allocateArray(Stuff *stuffArr) {

    Stuff *stuff = malloc(sizeof (Stuff) * ARR_SIZE);

    for (int i = 0; i < ARR_SIZE; i++) {
        (*(stuff + i)) = (Stuff) { i, i + i };
    }

    for (int i = 0; i < ARR_SIZE; i++) {
        printf("%d : %d\n", (stuff + i)->x, (stuff + i)->y);
    }

    stuffArr = stuff;
}

void deallocateArray(Stuff *stuffArr) {
    free(stuffArr);
}

int main(){
    Stuff * stuff = NULL;

    allocateArray(stuff);
    deallocateArray(stuff);

    return 0;
}
spatmac
  • 9
  • 2
  • 3
    It shouldn't work for either architecture. The line `stuffArr = stuff;` changes the local copy of `stuffArr`. It has no effect on variable `stuff` in `main`. – user3386109 Sep 14 '16 at 08:02
  • 1
    Also, `(*(stuff + i))` is the same as `stuff[i]`, and `(stuff + i)->x` is just `stuff[i].x` – user3386109 Sep 14 '16 at 08:04
  • _the x and y variables do not have an address when I try to access them_ : what is that supposed to mean ? – Jabberwocky Sep 14 '16 at 08:26
  • 1
    This is such a FAQ bug. Let me see if I can find a duplicate. – Lundin Sep 14 '16 at 08:30
  • This cannot work for the reasons pointed out in the comments and answers. The code you were running when it worked is not the code you show us here. – Jabberwocky Sep 14 '16 at 08:36
  • 2
    Apparently we have no canonical duplicate for this... we should probably create one, since this is such a common bug. – Lundin Sep 14 '16 at 08:37
  • 1
    There, [I made one](http://stackoverflow.com/questions/39486797/dynamic-memory-access-only-works-inside-function). – Lundin Sep 14 '16 at 09:23
  • @MichaelWalz Changed it up, still same error [screenshots](http://imgur.com/a/WeLJW) and [pastebin](http://pastebin.com/By8szrqp) – spatmac Sep 15 '16 at 02:52
  • This compiles ok, but is a program with errors. Variables are pased in C by value, so you cannot expect the pointer you pass to the function in `main` to be modified by the function. It can compile ok in 32bit, but it cannot work as you expect anywhere. – Luis Colorado Sep 15 '16 at 06:49
  • @spatmac the version in [pastebin](http://pastebin.com/By8szrqp) is just plain wrong. See the answers below. – Jabberwocky Sep 15 '16 at 06:54
  • @MichaelWalz Whiskers down there figured it out, thank you for taking time to look at it, turns I needed another std include – spatmac Sep 15 '16 at 19:32

4 Answers4

4

As user3386109 says, the code is not correct. Probably you are expecting that the allocateArray() function returns the allocated pointer, while you are passing the pointer by value, so that the variable stuff inside main() won't be updated.

You could either:

  • change the allocateArray() signature to void allocateArray(Stuff **stuffArr)
  • change the allocateArray() signature to Stuff *allocateArray()

(imho the second would be more idiomatic and clear).

I'd write it as:

Stuff *allocateArray(size_t count) {
    Stuff *stuff = (Stuff *) malloc(sizeof (Stuff) * count);

    if (! stuff)
        return NULL;

    for (int i = 0; i < count; i++) {
        stuff[i].x = i;
        stuff[i].y = 2 * i;

        printf("%d : %d\n", stuff[i].x, stuff[i].y);
    }

    return stuff;
}

void deallocateArray(Stuff *stuffArr) {
    if (stuffArr)
        free(stuffArr);
}

int main(){
    Stuff * stuff = allocateArray(ARR_SIZE);
    deallocateArray(stuff);

    return 0;
}
Marco Pantaleoni
  • 2,529
  • 15
  • 14
  • I just dont konw what the deal is, i changed it up to get rid of the goofy pointers and it wont compile as x64 [screenshots](http://imgur.com/a/WeLJW) and [pastebin](http://pastebin.com/By8szrqp) – spatmac Sep 15 '16 at 02:51
2

When you pass stuff in allocateArray you create a local variable, and when you remplace it at the end of the function, the variable in main is not updated

This should work, you just lost your pointer in the allocateArray function

#define ARR_SIZE 25

typedef struct {
    unsigned int x;
    unsigned int y;
}Stuff;

Stuff *allocateArray() {

   Stuff *stuff = malloc(sizeof (Stuff) * ARR_SIZE);

   for (int i = 0; i < ARR_SIZE; i++) {
       (*(stuff + i)) = (Stuff) { i, i + i };
   }

   for (int i = 0; i < ARR_SIZE; i++) {
       printf("%d : %d\n", (stuff + i)->x, (stuff + i)->y);
   }

   return stuff;
}

void deallocateArray(Stuff *stuffArr) {
  free(stuffArr);
}

int main(){
  Stuff * stuff = NULL;

  stuff = allocateArray();
  deallocateArray(stuff);

  return 0;
}
Clément Péau
  • 316
  • 3
  • 12
2

I copied and pasted your code into Visual Studio 2015 and compiled in both x86 and x64 and got the exact same output both times, however like user3386109 said, you aren't actually changing the variable stuff in main.

You could also use array indexing instead of adding integers to pointers like this.

for (int i = 0; i < ARR_SIZE; i++) {
    stuff[i] = (Stuff) { i, i + i };
}

for (int i = 0; i < ARR_SIZE; i++) {
    printf("%d : %d\n", stuff[i].x, stuff[i].y);
}
PhantomWhiskers
  • 218
  • 1
  • 10
  • I just dont konw what the deal is, i changed it up to get rid of the goofy pointers and it wont compile as x64 [screenshots](http://imgur.com/a/WeLJW) and [pastebin](http://pastebin.com/By8szrqp) – spatmac Sep 15 '16 at 02:49
  • You are missing `#include `. I copied your code from pastebin into visual studio, set the exact same project settings, and had same results as you, but then I noticed you were missing `stdlib.h`, added that in, and then it worked just fine in x64. Why it worked in x86 without `stdlib.h`, I do not know. – PhantomWhiskers Sep 15 '16 at 03:47
  • This has been bugging me for a day and a half.. Thanks a ton!!! – spatmac Sep 15 '16 at 03:54
  • No problem! If I had to guess why it worked in x86, Windows/MSVC probably has a default 32 bit implementation built in for functions like `malloc` and `free`, but doesn't have defaults for 64 bit. In general, always remember to include `stdlib.h` when doing dynamic memory allocation. – PhantomWhiskers Sep 15 '16 at 03:57
0

The good question is how does it works in x86. (it is undefined behavior). Try this:

#define ARR_SIZE 25
#include  "stdlib.h"
#include  "stdio.h"
typedef struct {
    unsigned int x;
    unsigned int y;
}Stuff;

void * allocateArray(Stuff *stuffArr) { //this row

    Stuff *stuff = (Stuff*)malloc(sizeof (Stuff) * ARR_SIZE);

    for (int i = 0; i < ARR_SIZE; i++) {
        (*(stuff + i)) = (Stuff) { i, i + i };
    }

    for (int i = 0; i < ARR_SIZE; i++) {
        printf("%d : %d\n", (stuff + i)->x, (stuff + i)->y);
    }

    stuffArr = stuff;
    return stuff; //this row
}

void deallocateArray(Stuff *stuffArr) {
    free(stuffArr);
}

int main(){
    Stuff * stuff = NULL;
    printf("%d\n",stuff);
    stuff=(Stuff*)allocateArray(stuff); ///this row
    printf("%p\n",stuff);
    deallocateArray(stuff);
    printf("%p\n",stuff);
    return 0;
}
jurhas
  • 613
  • 1
  • 4
  • 12
  • I just dont konw what the deal is, i changed it up to get rid of the goofy pointers and it wont compile as x64 [screenshots](http://imgur.com/a/WeLJW) and [pastebin](http://pastebin.com/By8szrqp) – spatmac Sep 15 '16 at 02:50