Merge pull request #928 from xexyl/1986-marshall-compilers
This commit is contained in:
5 files changed
+121
-9
No files matched your search
@@ -1,3 +1,4 @@
|
|||||||
marshall
|
marshall
|
||||||
marshall.orig
|
marshall.orig
|
||||||
prog.orig
|
prog.orig
|
||||||
|
marshall.alt
|
||||||
@@ -116,8 +116,8 @@ OBJ= ${PROG}.o
|
|||||||
DATA=
|
DATA=
|
||||||
TARGET= ${PROG}
|
TARGET= ${PROG}
|
||||||
#
|
#
|
||||||
ALT_OBJ=
|
ALT_OBJ= ${PROG}.alt.o
|
||||||
ALT_TARGET=
|
ALT_TARGET= ${PROG}.alt
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
|
|||||||
+96
-1
@@ -8,6 +8,13 @@ Eric Marshall
|
|||||||
make all
|
make all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
There is an alternate version. See the Alternate code section for the commentary
|
||||||
|
on why this is: there was a funny problem depending on the compiler and flags
|
||||||
|
where 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.
|
||||||
|
|
||||||
|
|
||||||
## Try:
|
## Try:
|
||||||
|
|
||||||
@@ -15,7 +22,95 @@ make all
|
|||||||
./marshall
|
./marshall
|
||||||
```
|
```
|
||||||
|
|
||||||
# Judges' remarks:
|
### 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.
|
||||||
|
|
||||||
|
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
|
||||||
|
to segfault but not another but when changing the state of the optimiser the
|
||||||
|
opposite would happen: the compiler that did not segfault suddenly did and the
|
||||||
|
one that did now worked! Another problem was an infinite loop also depending on
|
||||||
|
the optimiser.
|
||||||
|
|
||||||
|
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 what happens if we remove the infinite loop?
|
||||||
|
|
||||||
|
Once the loop is fixed 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 the program then 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
|
||||||
|
generates 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.
|
||||||
|
|
||||||
|
If the optimiser is enabled, however, we will see that it works fine before the
|
||||||
|
change to `_exit()`.
|
||||||
|
|
||||||
|
|
||||||
|
#### To use:
|
||||||
|
|
||||||
|
Due to the different conflicting problems 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, replaced by just `1`.
|
||||||
|
|
||||||
|
To try out the alternate version:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make alt
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `marshall.alt` as you would `marshall` above.
|
||||||
|
|
||||||
|
|
||||||
|
## Judges' remarks:
|
||||||
|
|
||||||
This program prints the name of the picture. The layout is somewhat
|
This program prints the name of the picture. The layout is somewhat
|
||||||
pretty though it is not the usual sort of output one would expect
|
pretty though it is not the usual sort of output one would expect
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
extern int
|
||||||
|
errno
|
||||||
|
;char
|
||||||
|
grrr
|
||||||
|
;main( r,
|
||||||
|
argv, argc ) char **argc ,
|
||||||
|
r ; char *argv[];{int P( );
|
||||||
|
#define x int i, j,cc[4];printf(" choo choo\n" ) ;
|
||||||
|
x ;if (P( ! i ) | cc[ ! j ]
|
||||||
|
& P(j )>2 ? j : i ){* argv[i++ +!-i]
|
||||||
|
; for (i= 0;; i++ );
|
||||||
|
_exit(argv[(int)*argc-2/cc[1*(int)*argc]|-1<<4]);printf("%d",P(""));}}
|
||||||
|
P ( a ) char a ; { a ; while( a > " B "
|
||||||
|
/* - by E ricM arsh all- */); }
|
||||||
+8
-6
@@ -144,12 +144,14 @@ was an `int`. He notes 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
|
original as possible. The line lengths are the same but some spaces had to be
|
||||||
changed to non-spaces.
|
changed to non-spaces.
|
||||||
|
|
||||||
As the fix was it worked for macOS but it did not work for modern linux, not
|
A very funny problem occurred depending on the compiler and whether or not the
|
||||||
before with gcc or after the fix with either gcc or clang, so Cody fixed that
|
optimiser is enabled that had to be fixed: one compiler would work fine but
|
||||||
too. This took some changes and commenting code out (commented out for the ASCII
|
another might enter an infinite loop or segfault but then once the optimiser
|
||||||
art as noted). It was a game of cat and mouse where one fix with one compiler
|
state was changed the compiler that worked no longer worked (in the same was as
|
||||||
caused it to segfault with the other but after commenting out two portions it
|
the other one not working) and the one that didn't work did! We encourage you to
|
||||||
works fine.
|
see the README.md file to see how odd this problem was and what Cody did to fix
|
||||||
|
it!
|
||||||
|
|
||||||
|
|
||||||
## [1986/wall](1986/wall/wall.c) ([README.md](1986/wall/README.md]))
|
## [1986/wall](1986/wall/wall.c) ([README.md](1986/wall/README.md]))
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user