I wonder if this is correct behavior. I was surprised to get this result when compiling and running the following C code with Apple clang version 14.0.0 (clang-1400.0.29.102) target arm64-apple-darwin21.6.0 on a M1 Pro 12.7.6 with cc -O2 file.c:
#include <stdio.h>
#include <stdlib.h>
unsigned long long factorial(int n)
{
unsigned long long fac = 1;
while (n > 0)
fac *= n;
return fac;
}
int main()
{
return factorial(1);
}
Compiling with -O2 and running this code gives "Trace/BPT trap".
Checking with LLDB:
$ lldb ./a.out
(lldb) target create "./a.out"
Current executable set to '/Users/engelen/Projects/Euler/a.out' (arm64).
(lldb) run
Process 79580 launched: '/Users/engelen/Projects/Euler/a.out' (arm64)
Process 79580 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x100003fb4)
frame #0: 0x0000000100003fb4 a.out`main at 20.c:9:3 [opt]
6 unsigned long long fac = 1;
7 while (n > 0)
8 fac *= n;
-> 9 return fac;
10 }
11
12 int main()
The loop is non-terminating. But a breakpoint trap is triggered at the return statement. The code should just hang in the loop IMO, not trap, because it never updates variable n (a correct factorial function should decrement n). Never seen this before (not since I started wiring C code in the 80s.)
If I change the update *=
into +=
then there is no trap.
You have an infinite loop. That’s undefined behaviour in C [1], and in this case the compiler is compiling that to a trap instruction.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] The story behind that is… well… complex. Honestly, I’m not 100% up to speed on whether it’s still undefined behaviour in the latest C and C++ standards. If you want to go down that rabbit hole, start here:
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm
Then follow the links. Looking for links from that post to other articles and from articles to that post. It’s a good way to spend a lazy Sunday afternoon.