Skip to content

Commit

Permalink
Add alt code to 1986/marshall
Browse files Browse the repository at this point in the history
Add the code before the fixes to the entry that prevented it from
working right depending on the compiler and optimiser (where having the
optimiser with one compiler would let it work with one and not work with
the other but having it disabled would reverse this in the same way) and
documented the ways the compilers conflicted for instructional value and
entertainment.

Updated .gitignore.
  • Loading branch information
xexyl committed Jul 15, 2023
1 parent c7c030c commit d792fbf
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 9 deletions.
1 change: 1 addition & 0 deletions 1986/marshall/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
marshall
marshall.orig
prog.orig
marshall.alt
4 changes: 2 additions & 2 deletions 1986/marshall/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ OBJ= ${PROG}.o
DATA=
TARGET= ${PROG}
#
ALT_OBJ=
ALT_TARGET=
ALT_OBJ= ${PROG}.alt.o
ALT_TARGET= ${PROG}.alt


#################
Expand Down
97 changes: 96 additions & 1 deletion 1986/marshall/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,109 @@ Eric Marshall
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:

```sh
./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
pretty though it is not the usual sort of output one would expect
Expand Down
14 changes: 14 additions & 0 deletions 1986/marshall/marshall.alt.c
Original file line number Diff line number Diff line change
@@ -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- */); }
14 changes: 8 additions & 6 deletions thanks-for-fixes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
changed to non-spaces.

As the fix was it worked for macOS but it did not work for modern linux, not
before with gcc or after the fix with either gcc or clang, so Cody fixed that
too. This took some changes and commenting code out (commented out for the ASCII
art as noted). It was a game of cat and mouse where one fix with one compiler
caused it to segfault with the other but after commenting out two portions it
works fine.
A very funny problem occurred depending on the compiler and whether or not the
optimiser is 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!


## [1986/wall](1986/wall/wall.c) ([README.md](1986/wall/README.md]))

Expand Down

0 comments on commit d792fbf

Please sign in to comment.