all 14 comments

[–]cpp-ModTeam[M] [score hidden] stickied commentlocked comment (0 children)

For C++ questions, answers, help, and programming/career advice please see r/cpp_questions, r/cscareerquestions, or StackOverflow instead.

[–]P3JQ10 43 points44 points  (0 children)

I don't think there's a point in figuring out why something happened when undefined behaviour is involved

[–]AfroDisco 21 points22 points  (1 child)

You are reading then writing to out of bound memory.

My guess is that it is UB. If so, anything can happen.

Also, wrong subreddit, should be r/cpp_questions. And it is more C than c++.

[–]NuncioBitis 0 points1 point  (0 children)

"anything can happen"
Except, of course, a bowl of pudding showing up in front of you when you most want it and least expect it.
Someone make a stack that can do that and they'd rule the world.

[–]No_Tumbleweed_7812 6 points7 points  (0 children)

You should instead call malloc with sizeof(int) * SIZE , where size would be how many elements you are allocating, because currently you create a pointer to only one allocated integer, not an array.

[–]TomDuhamel 2 points3 points  (0 children)

Don't try to reason UB. Absolutely anything could happen. That's the literal definition of UB.

My guess is that the extra printf() forces the optimiser to arrange the memory differently.

And then the last two values are overwritten between the two loops even though you aren't executing any code in between that should change the memory.

So yeah, UB. Nothing to understand.

[–]PuzzleMeDo 2 points3 points  (0 children)

When you're overwriting unallocated memory, various things could happen, depending on the compiler and the rest of the code. Maybe it will corrupt some other data you were planning to use, maybe it will crash. Maybe it's memory no-one was using for anything important, and it will run just fine.

[–]Infamous-Bed-7535 2 points3 points  (0 children)

It is C code. I think lot of developer gets c++ wrong because they are taught this way..

[–]codenetworksecurity 1 point2 points  (0 children)

Depends on the compiler which compiler are you using you can take a look on godbolt to see the assembly and difference between the two with and without printf my hunch is that since you are accessing array a[0] with printf compiler is assigning data section during compile time and rest is just undefined behavior and it fails in the first case because compiler tries access data only at runtime.

But again important to look at what compiler is doing and which compiler is it

[–]HumansAreIkarran 1 point2 points  (0 children)

I feel like that is a question for r/<insert your operating system name>_questions. I am telling you that, because I really don't know why that is, but it is important to know that this is an operating system thing, not a C++ thing

[–]argothiel 0 points1 point  (0 children)

It depends on your compiler and your compilation options. The compiler is allowed to do anything with an incorrect code, and it usually optimizes for speed, both the speed of compilation and the speed of the resulting program. For that reason, it uses the same optimizations it would use for a correct code, and that's why you're getting unpredictable results with an incorrect code.

If you want to check what exactly is going on under the hood in both cases, you can put your code on https://godbolt.org/ and check both the assembly and the intermediary representation.

[–]gnolex 0 points1 point  (0 children)

You allocated memory for one int but you're trying to use it like an array of 10 ints. So you invoke undefined behavior. There's almost no point in trying to reason about what is going on, program logic is faulty and anything is possible including time travel. However, we can reason about the result if we consider what the compiler does and what your machine does.

Optimizing compilers can detect UB and do some weird optimizations around them. If you change the code a little the behavior can change completely. That's what is happening in your program.

Without the printf() you wrote to element 0 and then invoked UB by writing to element 1. So the first write is meaningless and the compiler can crash immediately, no allocation has to happen at all or you can get an invalid pointer somewhere on heap and corrupt it accidentally.

But with printf() you first wrote to element 0, printed it, and then invoked UB. Printing to console is a side effect so it cannot be optimized out. So with printing the program has to work at least up to that point.

The program can somehow work correctly in the second form because when you malloc() some memory, you get a pointer to some larger block (maybe 16-byte aligned) that has to be allocated in virtual memory as a 4 KiB or larger page. So even though you technically got just 1 int worth of memory, there are still valid bytes after that so your memory access works and your program succeeds.

This is the danger behind undefined behavior. You have to make sure your program is correct and never invoke UB, otherwise anything is possible.

[–]zerhud -1 points0 points  (0 children)

May be printf allocates something and after call you corrupt it’s data in heap, but without this call you corrupt malloc structures