2

I have implemented a C calculator to analyses input. I have a struct (like a chained list) but on macOS I have to initialise through the init_null function or variable like value have an initial value. I have just one question: why?

On Linux, there was no issues.

typedef struct node_t {
    int value;
    char operator;
    struct node_t *left;
    struct node_t *right;
} node_t;

node_t *init_null(node_t *root) {
    root->value = NULL;
    root->operator = NULL;
    root->left = NULL;
    root->right = NULL;
    return root;
}

node_t *build_tree(const char *argv[], int *position) {
    node_t *new = malloc(sizeof(node_t));
    new = init_null(new); /*sinon erreur*/

    if (isdigit(*argv[*position])) {
        new->value = atoi(argv[*position]);
    } else/*Opérateur*/  {
        new->operator = *argv[*position];
        *position = *position + 1;
        new->left = build_tree(argv, position);
        *position = *position + 1;
        new->right = build_tree(argv, position);
    }
    return new;
}

When run, ./main * 2 + 3 4 should print (2 * (3 + 4)).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Can you give an example of the code that worked on Linux but not macOs? I don't know how else you would initialize the result of `malloc`. – AShelly Dec 19 '18 at 19:06
  • On linux, no need of the init_null function. My professor told me that It actually worked, but on my mac when I type new->value, it printed 15780894 for example. –  Dec 19 '18 at 19:14
  • 4
    Then you got lucky on Linux. There is no guarantee about the contents of memory returned from `malloc`. You should assume it contains random values on all platforms. (even if sometimes, in certain cases, which you probably can't predict correctly, it might be 0). – AShelly Dec 19 '18 at 19:16
  • `init_null` assigns `NULL` to `root->value`. Nothing in the rest of the code shown assigns a value to `root->value` (a.k.a. `new->value`). Therefore, without `init_null`, the behavior of using `root->value` is not defined. On the Linux system you tried, it just happened to behave as if it had been initialized to zero. – Eric Postpischil Dec 19 '18 at 19:16
  • Possible duplicate of [Why does malloc initialize the values to 0 in gcc?](https://stackoverflow.com/questions/8029584/why-does-malloc-initialize-the-values-to-0-in-gcc) – AShelly Dec 19 '18 at 19:17
  • 1
    "On linux, there was no issues." - that's purely by accident. Without `init_null` your code would not explicitly initialize `left` and `right` pointers in the first branch of `if`, which means without extra initialization that code is broken on Linux as well. Also, `root->value = NULL`, `root->operator = NULL` - this makes no sense. Don't assign `NULL` to non-pointer values. – AnT stands with Russia Dec 19 '18 at 19:26
  • 1
    *My professor told me that It actually worked* I hope that professor didn't see your source code and then tell you that. Seriously. Because if your professor did see your source code using uninitialized memory and then tell you that it worked, your professor doesn't understand undefined behavior, has no business teaching C, and you really do need to find another professor. – Andrew Henle Dec 19 '18 at 20:00
  • @AShelly I don't think it's a duplicate as the author doesn't know that that was the problem, although the answer may be similar. – John Dec 19 '18 at 20:22
  • Moreover, although the representation of null pointers on Linux and, I think, OS X is all-bits-zero, that is not a requirement of the C language, and it is not universal practice. Therefore, even if you could rely on `malloc()` to return memory that had been zeroed (or if you used `calloc()` instead), you would *still* need to separately initialize all pointers in the allocated space in order for your program to be strictly conforming. – John Bollinger Dec 19 '18 at 20:36

1 Answers1

2

Here is the problem:

There are at least 2 memory allocation methods you can use, malloc and calloc. The difference is that malloc DOES NOT initialise (or set) the successfully allocated memory to anything. There is an indeterminate explicit or implicit effect on the memory block, specific to the compiler at this compilation stance, as @EricPostpischil explained.

Whereas calloc sets the successfully allocated memory block to zero. Note that the arguments are slightly different.

Back to your concern, in Linux malloc just happened to allocate a block of memory that had zero in it, whereas on the macos platform there was something in it.

Use calloc if you thing you need it, otherwise do a memset of 0 to the allocated memory block.

John
  • 1,012
  • 14
  • 22
  • 1
    Be aware the specification of `malloc` is not that “It leaves whatever there was in that memory block there.” It is that malloc returns space for an object “whose value is indeterminate.” (C 2018 7.22.3.4 2.) This is because, in modern compilers, a call to `malloc` in source code is not necessarily translated to an actual call in CPU instructions. The compiler is allowed by the C standard to interpret the code and transform it, and modern compilers do aggressive transformations for optimization. When they see indeterminate values being used, they can transform the code in unexpected ways. – Eric Postpischil Dec 19 '18 at 19:46
  • @EricPostpischil I agree with you. I didn't attempt to get into a detailed answer. Even further, the compiler the author uses on the macos system may even actually set the memory to zero, which may the the unexpected/indeterminate behaviour. – John Dec 19 '18 at 19:49
  • 1
    Normally on linux memory is reset to 0 when a process is started, so that stuff from other processes doesn't leak in other processes. So a big enough malloc() will get new pages and will be zeroed, but small mallocs, in the beginning will always be 0, but after some frees they will probably be reused memory from the same process and contain garbage data. – LtWorf Dec 19 '18 at 21:18
  • @LtWorf Good point. I would expect a similar behaviour on a macOS machine as potentially described in this article http://www.cocoawithlove.com/2010/05/look-at-how-malloc-works-on-mac.html – John Dec 19 '18 at 21:23