-4

The following code snippet executes on a 64bit Ubuntu 14.04 while gives a seg fault in 32bit Ubuntu 14.04 . gcc version being same in both 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)

#include<stdio.h>
main ()

{

    int* a;
    int* b;
    *a = 40;
    b=a;
    printf ("%x ............. %p ...........%d \n",*a,a, *a);
}

The same thing works on the 32bit system if either of the two are done -

  1. comment out b=a
  2. Add a=malloc (sizeof(int)); before *a=40;

Can someone please explain this observation

Saurabh
  • 1
  • 1
  • 5
    The original code has undefined behavior. You are not assigning a valid memory address to `a`, so it has a random address. Dereferencing it to assign the 40 writes to random memory so anything can happen. The `malloc` fixes the error, but then you have a memory address if you do not call `free(a)`. Assigning `a` to `b` doesn't change any of this behavior. – Remy Lebeau May 28 '16 at 19:32
  • 2
    Turn on compiler warnings: *warning C4700: uninitialized local variable 'a' used* – Weather Vane May 28 '16 at 19:32
  • If you don't add **2**, it is *undefined behaviour* because you are trying to write to unallocated memory. **1** does not change anything because you are not using `b` anywhere. – Haris May 28 '16 at 19:33
  • 3
    `int *a; *a = 40;` is [undefined behaviour](https://en.wikipedia.org/wiki/Undefined_behavior) no matter what compiler or OS you use. – axiac May 28 '16 at 19:33
  • So OP was "lucky" that "something" worked. – Weather Vane May 28 '16 at 19:34
  • While the seg fault on the 32bit can be attributed to the missing malloc and hence the undefined behavior , why does it work on 64bit ? that's because of undefined behavior too ? – Saurabh May 28 '16 at 19:41
  • @Saurabh that's like asking: "I did not tie my shoe laces. Why did I not fall over?" – Weather Vane May 28 '16 at 19:43
  • 1
    @Saurabh If you don't look both ways before you cross the street, sometimes you'll get hit by a car and sometimes you won't. The solution is not to try to figure out when you can cross the street without looking both ways but to look both ways every time. – David Schwartz May 28 '16 at 20:04

1 Answers1

2

It's not a matter of 32-bit vs 64-bit, but an issue of using pointers which are not pointing to a valid memory address. In your code snippet, you have declared pointers *a and *b without actually pointing them anywhere, resulting in undefined behavior.

When using pointers always allocate immediately adequate memory, or point them to an existing corresponding variable.

For instance, all subsequent statements are valid:

int *a = NULL;
int *b = malloc(sizeof(int));
int c = 42;
int *d = &c;

By not initializing them, they are pointing to an arbitrary location. *a = 40; has probably worked "by chance" for you, as it could had been pointing to a memory space where you had access at the time. But, in the general case, this snippet should produce a segmetation fault in either operating system.

If you are not planning to point a pointer immediately to a valid memory address, consider initializing it to NULL, to avoid having a dangling pointer. You should never dereference a NULL pointer, but you may always check whether a pointer is NULL before attempting to do so. For example:

int *a = NULL;
if ( a != NULL ) {
  *a = 42;
}
int *b = a;
if ( b != NULL ) {
  printf("%d\n", *b);
}

This snippet won't print anything, as both *a and *b will be NULL, but your code won't produce a segmentation fault.

For what is worth, I got a segmentation fault as well on a Debian 64-bit system.

[edited to integrate @AnT's, @tuple_cat's and @Weather Vane's feedbacks]

Adama
  • 720
  • 2
  • 5
  • 23
  • 3
    I don't see how it has anything to do with *dynamic* memory specifically. You could just do `int c; int *a = &c;` and thus obtain a valid `a` and `*a`. No need to involve *dynamic* memory here. The concept of a "pointer" is not in any way tied to dynamic memory. – AnT stands with Russia May 28 '16 at 19:39
  • 3
    Also, `malloc` returns `void*`. Casting that is [unnecessary](http://stackoverflow.com/q/605845/3425536). – Emil Laine May 28 '16 at 19:41
  • @AnT Thanks for the feedback, I integrated it to make the answer more generic: when using pointers, they should be pointing somewhere valid. – Adama May 28 '16 at 19:58
  • @tuple_cat Thanks for pointing that thread out, I had no idea that it wasn't necessary. :) – Adama May 28 '16 at 19:59
  • 1
    Can you please add an explanation for *When using pointers always initialize them to `NULL`*? Dereferencing a `NULL` pointer won't work. But +1. – Weather Vane May 28 '16 at 20:03
  • @WeatherVane Thank you for your feedback, it should be clearer now. Please let me know if otherwise. – Adama May 28 '16 at 20:11