Update 1986/marshall/README.md

Reworded the explanation of the funny opposite/conflicting problems with
gcc and clang depending on if the optimiser is disabled or enabled, that
I fixed and added alt code to demonstrate it.
This commit is contained in:
Cody Boone Ferguson committed 2023-10-17 09:55:35 -07:00
1 parent 846339262f
commit 9cb85e0f18
2 files changed
+37 -35

No files matched your search

+27 -23
View File
@@ -8,12 +8,13 @@ Eric Marshall
make all make all
``` ```
There is an alternate version. See the Alternate code section for the commentary There is an alternate version. See the [Alternate code](#alternate-code) section
on why this is: there was a funny problem in modern systems where depending on for the commentary on why this is: there was a funny problem in modern systems
the compiler and flags it would work with one compiler with the optimiser but it where depending on the compiler and the optimiser it would work with one
would not work with the other; and if the optimiser state is changed the compiler with the optimiser but it would not work with the other; and if the
previous problematic compiler might work but the other one would not! We optimiser state is changed the previous problematic compiler might work but the
describe this in more detail below and we encourage you to read it. other one would not. We describe this in more detail below and we encourage you
to read it for entertainment if nothing else.
## Try: ## Try:
@@ -29,36 +30,37 @@ 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. 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) In some versions of gcc and clang (this was first discovered in fedora linux 38)
depending on whether or not the optimiser was enabled would cause one compiler if the compiler was enabled one compiler would generate code that segfaulted but
to generate code that segfaults but not another - but when changing the state the other one would not. However, when then disabling the optimiser the compiler
of the optimiser the opposite would happen: the compiler that did not cause a that had no problem suddenly did and the one that did suddenly did not.
segfault suddenly did and the one that did now worked! Another problem was an
infinite loop also depending on the optimiser. Another problem was that depending on the optimiser an infinite loop would be
entered.
The alternate code has the original fix for clang which works with some 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 compilers depending on the optimiser. When we refer to the code below we refer
to the alternate code. to the alternate code.
### The conflicting compiler problems: #### The conflicting compiler problems:
Below we describe the conflicting options that resulted in the need to modify Below we describe the conflicting options that resulted in the need to modify
the original code. the original code.
#### Linux ##### Linux
With the optimiser disabled GCC compiled the code to enter an infinite loop. 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 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 generates code that first prints the text twice (it should print it once) and
then immediately dumps core! then immediately dumps core!
But then what happens if we remove the infinite loop? But then there's that infinite loop. What happens if we remove it?
Once the loop is fixed if we compile with clang and the optimiser is disabled 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 all is okay. If however we compile with gcc and the optimiser is disabled the
string is printed once and the program then dumps core! Why is this? It is 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 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 removed and the optimiser disabled. If however we enable the optimiser clang
generates code that prints the string twice and dumps core just like before! will generate code that prints the string twice and dumps core just like before!
What about the call to `_exit()`? What about the call to `_exit()`?
The call was: The call was:
@@ -71,10 +73,10 @@ _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 Changing it to not refer to these variables and just exit 1 and the problems
disappear! disappear!
#### macOS ##### macOS
But as noted just because it works one way in linux does not mean it works the But as noted just because it works one way in linux does not mean it works the
same way in macOS! same way in macOS.
If the infinite loop is not removed/commented out and the optimiser is enabled 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 it works fine but if it's disabled it prints out the string and then enters an
@@ -89,7 +91,8 @@ $ ./marshall
Segmentation fault: 11 Segmentation fault: 11
``` ```
Observe how it doesn't print it twice. 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 If the optimiser is enabled, however, we will see that it works fine before the
change to `_exit()`. change to `_exit()`.
@@ -97,9 +100,10 @@ change to `_exit()`.
#### To use: #### To use:
Due to the different conflicting problems we instead offer the problematic code Due to the different conflicting problems with gcc and clang, we instead offer
as an alternate version whereas [marshall.c](marshall.c) has both the infinite the problematic code as an alternate version whereas [marshall.c](marshall.c)
loop and the complicated arg to `_exit()` commented out, replaced by just `1`. 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: To try out the alternate version:
+10 -12
View File
@@ -229,24 +229,22 @@ and gcc.
## [1986/marshall](1986/marshall/marshall.c) ([README.md](1986/marshall/README.md])) ## [1986/marshall](1986/marshall/marshall.c) ([README.md](1986/marshall/README.md]))
Cody got this to compile and work with clang and gcc. The optimiser being Cody got this to compile and work with clang and gcc. He noted that he tried to
keep the ASCII art as close to the original as possible. The line lengths are
the same but some spaces had to be changed to non-spaces.
This fix was very interesting and quite amusing, showing up problems with
compilers. This is a brief summary but much more is explained in the README.md,
giving which compilers had which problems in which systems: the optimiser being
enabled in one compiler let it work but broke it in the other; and disabling it enabled in one compiler let it work but broke it in the other; and disabling it
would let it work in the one that didn't work but suddenly the one that worked would let it work in the one that didn't work but suddenly the one that worked
would be broken. See below and the README.md file for more details. would be broken.
This problem was only after getting clang to compile, of course. It did not This problem was only after getting clang to compile, of course. It did not
compile it because it is more strict about the second and third args to `main()` compile it because it is more strict about the second and third args to `main()`
and the third arg was an `int`. Cody notes that he tried to keep the ASCII art and the third arg was an `int`.
as close to the original as possible. The line lengths are the same but some
spaces had to be changed to non-spaces.
As noted above, a very funny problem occurred depending on the compiler and We encourage you to read the README.md file to see how odd this problem was and
whether or not the optimiser was enabled that had to be fixed: one compiler
would work fine but another might enter an infinite loop or segfault but then
once the optimiser state was changed the compiler that worked no longer worked
(in the same was as the other one not working) and the one that didn't work did!
We encourage you to see the README.md file to see how odd this problem was and
what Cody did to fix it! what Cody did to fix it!