diff --git a/1986/marshall/README.md b/1986/marshall/README.md index 6f4a9c326..95171d375 100644 --- a/1986/marshall/README.md +++ b/1986/marshall/README.md @@ -8,13 +8,13 @@ Eric Marshall make all ``` -There is an alternate version. See the [Alternate code](#alternate-code) section -for the commentary on why this is: there was a funny problem in modern systems -where depending on the compiler and the optimiser it would work with one -compiler with the optimiser but it would not work with the other; and if the -optimiser state is changed the previous problematic compiler might work but the -other one would not. We describe this in more detail below and we encourage you -to read it for entertainment if nothing else. +There is an [alternate version](#alternate-code). The reason is a funny problem: +in modern systems, depending on the platform, compiler and the optimiser, it +would work with one compiler with the optimiser but it would not work with the +other; and if the optimiser state is changed the previous problematic compiler +might work but the other one would not. We describe this in more detail in +[compilers.md](compilers.md) and we encourage you to read it for entertainment +if nothing else. ## Try: @@ -25,93 +25,29 @@ to read it for entertainment if nothing else. ## Alternate code: -As some changes had to be made due to the problem of conflicting compiler -options briefly noted above we provide the code that demonstrates the problem so -you can see if your compiler has the problem as described below. +Due to the different [conflicting problems](compilers.md) with gcc and clang, we +instead offer the problematic code as an alternate version whereas +[marshall.c](marshall.c) has both the infinite loop and the complicated arg to +`_exit()` commented out, changing the value passed into `_exit()` to `1`. -In some versions of gcc and clang (this was first discovered in fedora linux 38) -if the compiler was enabled one compiler would generate code that segfaulted but -the other one would not. However, when then disabling the optimiser the compiler -that had no problem suddenly did and the one that did suddenly did not. +### Alternate build: -Another problem was that depending on the optimiser an infinite loop would be -entered. +To see if your compiler has the problems noted: -The alternate code has the original fix for clang which works with some -compilers depending on the optimiser. When we refer to the code below we refer -to the alternate code. - -#### The conflicting compiler problems: - -Below we describe the conflicting options that resulted in the need to modify -the original code. - -##### Linux - -With the optimiser disabled GCC compiled the code to enter an infinite loop. -Enabling the optimiser and it worked fine. But if the optimiser is enabled clang -generates code that first prints the text twice (it should print it once) and -then immediately dumps core! - -But then there's that infinite loop. What happens if we remove it? - -Once the loop is removed if we compile with clang and the optimiser is disabled -all is okay. If however we compile with gcc and the optimiser is disabled the -string is printed once and then the program dumps core! Why is this? It is -because of the call to `_exit()` (see below). Clang works fine with the loop -removed and the optimiser disabled. If however we enable the optimiser clang -will generate code that prints the string twice and dumps core just like before! -What about the call to `_exit()`? - -The call was: - - -```c -_exit(argv[(int)*argc-2/cc[1*(int)*argc]|-1<<4]); -``` - -Changing it to not refer to these variables and just exit 1 and the problems -disappear! - -##### macOS - -But as noted just because it works one way in linux does not mean it works the -same way in macOS. - -If the infinite loop is not removed/commented out and the optimiser is enabled -it works fine but if it's disabled it prints out the string and then enters an -infinite loop. - -After we fix the infinite loop if we change the `_exit()` call in macOS and -disable the optimiser we might get something like: - -```sh -$ ./marshall - choo choo -Segmentation fault: 11 -``` - -Observe how it doesn't print it twice. But of course it segfaults so it's not -right either. - -If the optimiser is enabled, however, we will see that it works fine before the -change to `_exit()`. - - -### Alternate use: - -Due to the different conflicting problems with gcc and clang, we instead offer -the problematic code as an alternate version whereas [marshall.c](marshall.c) -has both the infinite loop and the complicated arg to `_exit()` commented out, -changing the value passed into `_exit()` to `1`. - -To try out the alternate version: ```sh make alt ``` -Use `marshall.alt` as you would `marshall` above. +### Alternate run: + +```sh +./marshall.alt +``` + +Does it work in your system? That is does it not segfault, does it print it only +once and does it not enter an infinite loop? Or more generally does it print the +text exactly once and then exit? ## Judges' remarks: diff --git a/1986/marshall/compilers.md b/1986/marshall/compilers.md new file mode 100644 index 000000000..82a8ae61f --- /dev/null +++ b/1986/marshall/compilers.md @@ -0,0 +1,93 @@ +# Conflicting compilers and optimisers that broke this entry in 2023 + +As briefly noted in the [README.md](README.md) gcc and clang caused different +problems with this entry depending on the optimiser being enabled or not, where +if the optimiser was enabled it would work with one compiler and not the other. +But if you then disabled the optimiser the opposite problem would occur: the +working compiler would no longer work and the non-functional one would start to +work! And then there's the problem of linux versus macOS causing problems. + +The [alternate code](marshall.alt.c) (source code) demonstrates the problem so +you can see if your compiler has the problem as described below. + +In some versions of gcc and clang (this was first discovered in fedora linux 38) +if the compiler was enabled one compiler would generate code that segfaulted but +the other one would not. However, when then disabling the optimiser the compiler +that had no problem suddenly did and the one that did suddenly did not. But +segfaulting was not by any means the only problem. + +Another problem was that depending on the optimiser an infinite loop would be +entered. But then removing it would cause other problems as well, including a +segfault. + +It was not only one compiler that dumped core. Both dumped core with other +behaviour, depending on what changes in code were made and the optimiser being +on or off. Clang in macOS also dumped core! + +The [alternate code](README.md#alternate-code) (README.md) has the original fix +for clang which works with some compilers depending on the optimiser. When we +refer to the code below we refer to the alternate code. + +## The conflicting compiler problems: + +Below we describe the conflicting options that resulted in the need to modify +the original code. + +### Linux + +With the optimiser disabled GCC compiled the code to enter an infinite loop. +Enabling the optimiser and it worked fine. But if the optimiser is enabled clang +generates code that first prints the text twice (it should print it once) and +then immediately dumps core! + +But then there's that infinite loop. What happens if we remove it? + +Once the loop is removed if we compile with clang and the optimiser is disabled +all is okay. If however we compile with gcc and the optimiser is disabled the +string is printed once and then the program dumps core! Why is this? It is +because of the call to `_exit()` (see below). + +Clang works fine with the loop removed and the optimiser disabled. If however we +enable the optimiser clang will generate code that prints the string twice and +dumps core just like before! What about the call to `_exit()`? + +The call was: + + +```c +_exit(argv[(int)*argc-2/cc[1*(int)*argc]|-1<<4]); +``` + +Changing it to not refer to these variables and just exit 1 and the problems +disappear! + +### macOS + +But then there was macOS which had another problem! + +If the infinite loop is not removed/commented out and the optimiser is enabled +it works fine but if it's disabled it prints out the string and then enters an +infinite loop! + +After we fix the infinite loop if we change the `_exit()` call in macOS and +disable the optimiser we might get something like: + +```sh +$ ./marshall + choo choo +Segmentation fault: 11 +``` + +Observe how it doesn't print it twice. But of course it segfaults so it's not +right either. + +If the optimiser is enabled, however, we will see that it works fine before the +change to `_exit()`. + +## Summary + +And that is the tale of a little engine train that +could...eventually! Or perhaps it's the compilers, optimisers and OSes that +eventually could? + +Whichever you wish it to be, it now works with both clang and gcc! Choo choo!