1

Below is my code :

p = (float *) malloc(sizeof(float) * n);
p1 = p; // p1 is float*
p--; // Will this result in a seg-fault?

I am guessing yes because I am trying to access memory outside allocated space. Please could somebody confirm?

Edit After seeing hobbs' answer I could not resist asking this too.

I strongly believe this will not result in a seg fault

printf("%f",p[n]); // because n is legally allocated for p
sjsam
  • 21,411
  • 5
  • 55
  • 102
  • 2
    Related to and maybe duplicate of [Decrementing a pointer out of bounds; incrementing it into bounds](http://stackoverflow.com/q/18186987/1708801) and [Does applying post-decrement on a pointer already addressing the base of an array invoke undefined behavior?](http://stackoverflow.com/q/30512669/1708801) – Shafik Yaghmour May 29 '15 at 17:33
  • 3
    Instead of guessing why don't you try it? – JAL May 29 '15 at 17:35
  • 2
    @JAL You can't "try" undefined behaviour – Eugene Sh. May 29 '15 at 17:35
  • 1
    @JAL by definition *try it out* when it comes to undefined behavior does not tell you much – Shafik Yaghmour May 29 '15 at 17:37

3 Answers3

4

You're not accessing any memory at all; you're doing pointer arithmetic. Using pointer arithmetic to obtain a pointer that isn't inside an object or one past the end of an array is undefined behavior, so anything could happen, including a segfault. However, on most reasonable systems, nothing will happen unless you try to do so something with *p. At that point, anything could happen, from receiving garbage values, to a crash/segfault, to global thermonuclear war.

hobbs
  • 223,387
  • 19
  • 210
  • 288
3

It will result in undefined behavior. If you try to do anything with p by de-referencing it, the program will either throw a segmentation fault or do something else you don't want.

Lawrence Aiello
  • 4,560
  • 5
  • 21
  • 35
  • 1
    Why would it be UB? It is just a pointer decrement, without any attempt to dereference it. – Eugene Sh. May 29 '15 at 17:35
  • 'int *p;' in a function would therefore be UB, even if it was malloced in the next line. – Martin James May 29 '15 at 17:40
  • @EugeneSh. see first comment of the question by ShafikYaghmour – bolov May 29 '15 at 17:42
  • @EugeneSh. yes, it is UB. That's why libraries that know what they are doing and need to hold pointers to another device's memory hold it as `unsigned long` and not as pointers. – bolov May 29 '15 at 17:44
  • @bolov - does that not make dereferencing it somewhat difficult? – Martin James May 29 '15 at 17:46
  • @hobbs So how is that used like everywhere in memory mapped register definitions (embedded mostly)? – Eugene Sh. May 29 '15 at 17:47
  • ^^ there my be timer or I/O controller registers at that address – Martin James May 29 '15 at 17:47
  • 1
    Its seems that all my embedded firmware has galloping UB:( – Martin James May 29 '15 at 17:48
  • Also drivers on more complex, desktop OS:( – Martin James May 29 '15 at 17:49
  • It's the second time my world of embedded firmware is about to crash. The first one was [here](http://stackoverflow.com/questions/30262801/what-is-my-best-approach-to-determining-compiler-behaviour-for-empty-infinite-lo) – Eugene Sh. May 29 '15 at 17:50
  • @EugeneSh well 2 reasons: 1 they don't know what they are doing and it just happens that the compiler implementation doesn't result in any negative effect. 2 they know what they are doing and the compiler used guarantees that althought the standard says it is UB, it (the compiler) guarantees that in it's implementation it is well defined and ok – bolov May 29 '15 at 17:50
  • @hobbs I thinks it is more like they implement data pointers with unsigned integers (required size) and this has no negative effect if you create a value that is not a valid value of a pointer. – bolov May 29 '15 at 17:54
  • 1
    @EugeneSh. using pointer arithmetic to obtain a pointer other than inside an object or one past the end of an array is UB. Converting pointer<->integer is merely implementation-defined, not UB. – hobbs May 29 '15 at 17:55
  • 1
    Can you guys please take this to a private discussion? I'm tired of getting notifications. – Lawrence Aiello May 29 '15 at 17:55
1

You don't always encounter a seg fault when accessing memory outside the allocated area. The memory accessed may be allocated, just to something else. So either case could happen, but both are undesirable behavior.

The pointer p is allowed to contain a "bad" pointer and no undesirable behavior will occur. Consider its state when it is uninitialized. If you use the pointer by dereferencing it, then you will either encounter a seg fault or access someone else's memory, and that is undesirable behavior.

Dko
  • 820
  • 6
  • 12
  • I guess the OP's point is that no such access is being performed. A pointer is decremented, that's it. No dereference takes place. – Martin James May 29 '15 at 17:36
  • That's true. @sjsam, the pointer p is allowed to contain a "bad" pointer and no undesirable behavior will occur. If you use the pointer by dereferencing it, then you will either encounter a seg fault or access someone else's memory, and that is undesirable behavior. – Dko May 29 '15 at 17:39
  • @MartinJames: You're right, I am sure I won't dereference p. :-) – sjsam May 29 '15 at 18:16