XEmacs und programmieren

Lutz Donnerhacke lutz at iks-jena.de
Die Apr 15 10:50:23 CEST 2003


* Roland Wolters wrote:
> Gut, das regele ich damit, dass ich den Dateinamen dahinter schreibe,
> aber so weit ich das richtig verstanden habe, ist es doch gerade der Sinn
> des "compile" Knopfes, dass ich eben nicht den Dateinamen noch extra dazu
> schreiben muss, oder?

Man muß es deswegen angeben, weil in größeren Projekten gerade die kleinen
Dateien nicht einzeln übersetzt werden sollen. Wenn nichts angegeben ist,
nimmt make die Datei "Makefile". Wenn auch die fehlt, versucht er das als
Argument angegebene Ziel zu bauen. (Wenn Du also "make test.c" aufrufst, ist
nichts zu tun, weil test.c ja schon da ist.) Du kannst also "make test.o"
oder "make test" angeben.

Andere Sprachen haben einen komplexeren Bau, um besondere Probleme der
Elaboration in den Griff zu bekommen.

Kurz:
$ cat > r.h
#ifndef r_h
#define r_h

class r {
   int i;
 public:
   r(int x) : i(x) {}
   operator int(void) const;
};

#include "t.h"
extern t r1;
#endif

$ cat > t.h
#ifndef t_h
#define t_h

class t {
   int i;
 public:
   t(int x) : i(x) {}
   operator int(void) const;
};
   
#include "r.h"
extern r t1;
#endif

$ cat > main.cc
#include "t.h"
#include "r.h"
#include <iostream>

int main(void) {
   std::cout << "t1 = " << t1 << std::endl;
   std::cout << "r1 = " << r1 << std::endl;
}
$ cat > r.cc
#include "r.h"
#include "t.h"

t r1(5);

r::operator int(void) const {
   return i + r1;
}

$ cat > t.cc
#include "t.h"
#include "r.h"

r t1(5);

t::operator int(void) const {
   return i + t1;
}

$ cat > Makefile

t_r: main.o t.o r.o
	g++ -o $@ $^

r_t: main.o r.o t.o
	g++ -o $@ $^

main.o: main.cc t.h r.h

t.o: t.cc t.h r.h

r.o: r.cc r.h t.h


Wie man sieht, ist das offensichtlich konstruiert, jedoch in größeren
Programmen ohne Probleme generierbar. Wenn man es kompiliert erreicht man
einen erstklassigen Segmentation Fault: das Programm stürzt schlicht ab.
Ein anderer typischer Fehler, der dabei auftritt ist: Unterschiedliche
Initialisierungswerte, je nach Linkreihenfolge.

Dieses Fälle ist in anderen Sprachen erfaßt, da sie grundsätzlich nicht
tolerierbar sind:

$ cat > r.ads
package r is
   type r is private;
   
   function make(x : Integer) return r;
   function get(v : r) return Integer;

   function get_constant return Integer;
private
   type r is new Integer;
end r;
$ cat > t.ads
package t is
   type t is private;
   
   function make(x : Integer) return t;
   function get(v : t) return Integer;
   
   function get_constant return Integer;
private
   type t is new Integer;
end t;
$ cat > main.adb
with r,t,Ada.Text_IO;
use Ada.Text_IO;

procedure main is
begin
   Put_Line("t1 =" & Integer'Image(t.get_constant));
   Put_Line("r1 =" & Integer'Image(r.get_constant));
end main;
$ cat > r.adb
with t;
   
package body r is
   function make(x : Integer) return r is
   begin
      return r(x);
   end make;
   
   r1 : constant t.t := t.make(5);

   function get(v : r) return Integer is
   begin
      return Integer(v) + t.get(r1);
   end get;

   function get_constant return Integer is
   begin
      return t.get(r1);
   end get_constant;
end r;
$ cat > t.adb
with r;

package body t is
   function make(x : Integer) return t is
   begin
      return t(x);
   end make;
   
   t1 : constant r.r := r.make(5);
   
   function get(v : t) return Integer is
   begin
      return Integer(v) + r.get(t1);
   end get;

   function get_constant return Integer is
   begin
      return r.get(t1);
   end get_constant;
end t;
$ gnatmake main.adb       # Makefile ist unnötig, gnatmake liest den Source.
gnatbind -x main.ali
error: elaboration circularity detected
info:    "t (body)" must be elaborated before "r (body)"
info:       reason: Elaborate_All probably needed in unit "r (body)"
info:       recompile "r (body)" with -gnatwl for full details
info:          "t (body)"
info:             must be elaborated along with its spec:
info:          "t (spec)"
info:             which is withed by:
info:          "r (body)"

info:    "r (body)" must be elaborated before "t (body)"
info:       reason: Elaborate_All probably needed in unit "t (body)"
info:       recompile "t (body)" with -gnatwl for full details
info:          "r (body)"
info:             must be elaborated along with its spec:
info:          "r (spec)"
info:             which is withed by:
info:          "t (body)"

gnatmake: *** bind failed.

Folgt man den Hinweisen, so zeigt er auf die Benutzung des
gegenüberliegenden "make" und meint, da wäre der Fehler:
t.adb:9:26: warning: call to "make" may raise Program_Error  
 
Legt man die Elaborationsreihenfolge mit pragma Elaborate_Body fest, so
gestattet er den Ruf von Funktionen aus dem anderen Package erst gar nicht.

Kurz: Man muß gehörig Grips in die Compilierung stecken.

-- 
tlug Mailingliste
Archiv: http://www.tlug.de/archiv/
http://schwarz.thueday.de/mailman/listinfo/tlug_allgemein