Merge pull request #1213 from xexyl/1986-marshall-compilers
This commit is contained in:
2 files changed
+115
-86
No files matched your search
+22
-86
@@ -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:
|
||||
|
||||
@@ -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 <strike>engine</strike> 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!
|
||||
Reference in new issue
Block a user