ldmud-3.2.9/doc/
ldmud-3.2.9/doc/efun/
ldmud-3.2.9/mud/
ldmud-3.2.9/mud/heaven7/
ldmud-3.2.9/mud/heaven7/lib/
ldmud-3.2.9/mud/lp-245/
ldmud-3.2.9/mud/lp-245/banish/
ldmud-3.2.9/mud/lp-245/doc/
ldmud-3.2.9/mud/lp-245/doc/examples/
ldmud-3.2.9/mud/lp-245/doc/sefun/
ldmud-3.2.9/mud/lp-245/log/
ldmud-3.2.9/mud/lp-245/obj/Go/
ldmud-3.2.9/mud/lp-245/players/lars/
ldmud-3.2.9/mud/lp-245/room/death/
ldmud-3.2.9/mud/lp-245/room/maze1/
ldmud-3.2.9/mud/lp-245/room/sub/
ldmud-3.2.9/mud/lp-245/secure/
ldmud-3.2.9/mud/morgengrauen/
ldmud-3.2.9/mud/morgengrauen/lib/
ldmud-3.2.9/mud/sticklib/
ldmud-3.2.9/mud/sticklib/src/
ldmud-3.2.9/mudlib/uni-crasher/
ldmud-3.2.9/pkg/
ldmud-3.2.9/pkg/debugger/
ldmud-3.2.9/pkg/diff/
ldmud-3.2.9/pkg/misc/
ldmud-3.2.9/src/autoconf/
ldmud-3.2.9/src/bugs/
ldmud-3.2.9/src/bugs/MudCompress/
ldmud-3.2.9/src/bugs/b-020916-files/
ldmud-3.2.9/src/bugs/doomdark/
ldmud-3.2.9/src/bugs/ferrycode/ferry/
ldmud-3.2.9/src/bugs/ferrycode/obj/
ldmud-3.2.9/src/bugs/psql/
ldmud-3.2.9/src/done/
ldmud-3.2.9/src/done/order_alist/
ldmud-3.2.9/src/done/order_alist/obj/
ldmud-3.2.9/src/done/order_alist/room/
ldmud-3.2.9/src/gcc/
ldmud-3.2.9/src/gcc/2.7.0/
ldmud-3.2.9/src/gcc/2.7.1/
ldmud-3.2.9/src/hosts/
ldmud-3.2.9/src/hosts/GnuWin32/
ldmud-3.2.9/src/hosts/amiga/NetIncl/
ldmud-3.2.9/src/hosts/amiga/NetIncl/netinet/
ldmud-3.2.9/src/hosts/amiga/NetIncl/sys/
ldmud-3.2.9/src/hosts/i386/
ldmud-3.2.9/src/hosts/msdos/byacc/
ldmud-3.2.9/src/hosts/msdos/doc/
ldmud-3.2.9/src/hosts/os2/
ldmud-3.2.9/src/hosts/win32/
ldmud-3.2.9/src/util/
ldmud-3.2.9/src/util/erq/
ldmud-3.2.9/src/util/indent/hosts/next/
ldmud-3.2.9/src/util/xerq/
ldmud-3.2.9/src/util/xerq/lpc/
ldmud-3.2.9/src/util/xerq/lpc/www/
Short: Virtual variables
Date: 981208
Type: Bug
State: Done: Fixed
From: Alfe
See also: b-981201, p-990217

Virtual variables don't work properly. A (German) description follows:
,---------.
|    From | Alfe
|      To | Alfe, Amylaar, Arkon, Carador, Demos, Fangorn, Macbeth, Mentar,
|         | Monst and Ugh
|    Date | Thu Jun  6 00:01:43 1996
| Subject | Der Virtual Bug!
`---------'

  P R O L O G     --     Die Entdeckung

Nach langem Suchen ist es uns endlich gelungen, eine Minimalversion des
beruechtigten Virtual-Bugs aus gewaltigen Files herauszuarbeiten und sogar
ein wesentliches Merkmal zu entdecken!


  T E I L   I     --     Der Bug

Der ::-Operator (nur zur Compilezeit ueberhaupt von Bedeutung) ist der Dreh-
und Angelpunkt des Fehlers. Definiert ist er so, dass der Bezeichner vor ihm
dann weggelassen werden kann, wenn er die erste inheritete Klasse
bezeichnet,
die die Lfun hinter dem Operator definiert. Insbesondere also, wenn diese
Lfun nur ein einziges Mal inheritet wird.

An diese Definition haelt sich der Compiler leider nicht immer. Eine unguen-
stige Kombination von virtual und objekt-globalen Variablen fuehrt dazu,
dass eine gesamte Klasse bei der Lfun-Suche uebersprungen wird und statt ih-
rer eine Klasse verwendet wird, die nicht direkte Basisklasse ist, sondern
nur Basisklasse der Uebersprungenen!


  T E I L   I I     --     Die Variable

Wie sich herausstellte, ist eine kleine unscheinbare Variable schuld daran,
dass dieser Fehler in Erscheinung tritt. Kommentiert man sie aus, ist der
Fehler verschwunden.

Diese Variable muss in der tiefsten der drei beteiligten Klassen definiert
werden.

Eine etwas ueberraschende Erkenntnis, dass eine Variable Einfluss auf die
Abarbeitung von Funktionsaufrufen haben soll.


  T E I L   I I I     --     Virtual

Diese tiefste Klasse muss zusaetzlich von der mittleren `virtual' inheritet
werden, was diesem Phaenomen seinen Namen gegeben hat.

`virtual' setzt voraus, dass man in einem komplexen Vererbungsbaum keine
Klasse an einer Stelle `virtual' und an einer anderen nicht `virtual' inhe-
ritet; man muss es immer gleich machen. In diesem Fall wird diese Regel be-
achtet, dennoch tritt der Fehler auf.

Mit Entfernen des Schluesselwortes `virtual' verschwindet der Fehler jedoch.


  T E I L   I V     --     Das Beispiel

Unter ~alfe/virtual/{a,b,c}.c findet sich ein auf das Noetigste zurechtge-
stutztes Beispiel. c inheritet b normal, b inheritet a virtuell. a enthaelt
die entscheidende Variable.

Zum Testen sollte in c die Lfun foo() aufgerufen werden, die von allen
drei Klassen definiert wird. c ruft dann zuerst ::foo() auf, danach
b::foo().
Beide Aufrufe sollten das gleiche Ergebnis erzielen, doch die Debug-Ausgaben
sprechen eine deutliche Sprache.

::foo() ruft tatsaechlich a::foo() auf, obwohl a gar nicht direkt von c ge-
erbt wird und b diese Funktion ueberlagert!


  E P I L O G     --     Die Konsequenzen

Endlose Fehlersuche, die haeufig mit unbefriedigenden Loesungen beendet wur-
den, kann, sollte sie auf diesen Bug zurueckzufuehren sein, demnaechst ver-
mieden werden; entweder, weil jetzt bekannt ist, dass der ::-Operator ohne
vorangestelltes Argument fehlerhaft ist, oder weil der Fehler im Driver
behoben wird.

In jedem Fall wird die Aufklaerung dieses Phaenomens die Akzeptanz von
`virtual' sicher erhoehen.
                                        Ugh & Alfe

PS: Die Files aus dem Beispiel:
/players/alfe/virtual/a.c:
        int i;

        mixed foo() {
          write("a!\n");
        }

/players/alfe/virtual/b.c:
        virtual inherit "players/alfe/virtual/a";

        mixed foo() {
          write("  b!\n");
        }

/players/alfe/virtual/c.c:
        inherit "players/alfe/virtual/b";

        status foo() {
          write("    c!\n"
                "    calling ::foo();\n");
          ::foo();
          write("    c!\n"
                "    calling b::foo();\n");
          b::foo();
        }

----------------------------------------------------------------------------
Christian Mudra                         Just remember what your mother
c_mudra@informatik.uni-kl.de                   always told you:
Universitaet Kaiserslautern        "When you open windows you let in bugs".