Global angelegtes Objekt in C++ funktioniert nicht

Gast #2490476
Lesenswert?

Hallo,

Folgendes Problem:
Global angelegte Instanzen funktioniern nicht.

Ich habe eine Klasse angelegt, mit einer öffentlichen Funktion. Es geht 
nicht um die Funktion der Klasse da diese nur zum Debuggen dient und 
daher sehr einfach gehalten ist.

Die Klasse sieht so aus:

Header:
1
class Test
2
{
3
  private:
4
  int al,bl;
5
  
6
  public:
7
  Test(int a, int b);
8
  void Write(int a, int b);
9
};

CPP
1
void Test::Write(int a, int b)
2
{
3
  al=a+1;
4
  bl=b+1;
5
}
6

7
Test::Test(int a, int b)
8
{
9
  Write(a, b);
10
}


Erzeuge ich eine Instanz der Klasse innerhalb einer Funktion dann 
funktioniert das auch einwandfrei.

Beispiel:
1
int main(void)
2
{
3
    Test t1(1,1);
4
    while (1) asm volatile("nop");
5
}

Erzeuge ich die Instanz global sieht es für mich so aus als ob die 
Rücksprungadresse für den Return nicht mehr passt und er springt 
irgendwo im Programm hin und das Programm läuft nicht mehr.

Beispiel:
1
Test t1(1,1);
2

3
int main(void)
4
{
5
   while (1) asm volatile("nop");
6
}


Muss man wenn man C++ verwendet noch spezielle Speicherbereiche 
initialisieren?

Oder ist das vielleicht ein Bug von g++ da OOP für µCs nicht vorgesehen 
ist?

Ich verwende AVRStudio 5.0
Würde mich für zahlreiche Ideen und Tipps freuen ;)

Der Fehler lässt sich mit dem angegebenen Quellcode nachstellen.
#2490511
Lesenswert?

Martin schrieb:
> Ich habe den avr-g++ verwendet. Im AVR Studio gibts auch extra ein
> Template für C++ Anwendungen. Es funktioniert auch wenn ich die Instanz
> lokal erzeuge.

Beim avr-g++ funktioniert auch noch einiges nicht, kannst du hier im 
Forum mal suchen...

Ich tippe auf Bug.

Nim C, du kannst auch in C "objektorientiert" programmieren. Ist 
ziemlich umständlich aber geht...

Gutes Beispiel: GLib oder GTK.


mfg Andreas
#2490512
Lesenswert?

Laut http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus 
sollte es eigentlich gehen.

Irgendwoe im Hinterkpof hatte ich aber mal gespeichert, daß die 
Initialisierung globaler Variablen nicht klappen soll, und einmal hatte 
ich es probiert bin undwar ebenfalls damit gescheitert.
Daraufhin bin ich auf eine lokale Variable ausgewichen und hatte 
vergessen, mich um den Grund zu kümmern.

Du bist jedenfalls nicht allein mit dem Problem.
#2490608
Lesenswert?

Mit einer älteren Version vom avr-gcc / avr-libc habe ich da nie 
Probleme gehabt. Allerdings habe ich das nicht mit aktuellen Versionen 
getestet.

Man muss bei solchen Initializern natürlich aufpassen, dass man darin 
(wie hier) nur das eigene Objekt anspricht und nicht noch andere 
statische Objekte oder irgendwelche noch nicht initialisierte I/O. Denn 
jedweder Initialisierungscode in main() ist zu diesem Zeitpunkt noch 
nicht gelaufen, die Interrupts sind abgeschaltet und die Reihenfolge des 
Aufrufs statischer Initializer ist unspezifiziert.

Was also oft nicht geht: Trace-Ausgaben bereits in Initializern 
auszuführen. Weil die Initialisierung vom dazu verwendeten Ausgabedevice 
noch nicht stattgefunden hat.

Ausserdem kann es sein, dass der Debugger einen seltsame Kontext 
anzeigt, denn die Initializer werden ja nicht aus main() heraus 
aufgerufen, sondern aus dem Initialisierungscode der avr-libc heraus.
Gast #2490648
Lesenswert?

Was vielleicht noch interessant zum Fehlerfinden sein kann:
Wenn ich Optimierung -O2 einstelle funktionierts auch mit der globalen 
Instanzierung. Ich weiß nur nicht genau was -O2 alles bewirkt...Mit -Os 
und -O0 funktionierts nicht.
#2490751
Lesenswert?

Grad mal mit Studio 4 und 5 ausprobiert.

Mit Studio 4 funktioniert es, der Initialisierungsvektor wird erzeugt 
und der Initializer wird aufgerufen.

Mit Studio 5 (5.0.1163) funktioniert es nicht. Die Liste der 
Iniitialisierungsvektoren bleibt leer. Das .o File enthält keine 
entsprechende Section, auch die Debug-Sektionen fehlen.

Grund: Das Projekt-Template vom Studio 5 für C++ fehlt und das C 
Template verarbeitet .cpp Files nicht vergleichbar zu C Quellcode. Die 
Compiler-Optionen fehlen praktisch vollständig.

Abhilfe, Quick&Dirty: Endung .c verwenden und "-x c++"" hinzufügen, 
damit .c Files als C++ Files übersetzt werden (verified).

Oder eigenes Makefile verwenden. Oder C++ Template bauen. Vielleicht 
gibts auch andere Wege, das war mein erster Versuch mit dem Studio 5.
#2490835
Lesenswert?

Johann L. schrieb:

> Die Endung ist mit -x egal. Lediglich die Reihenfolge spielt ne Rolle:
> -x muss vor den Dateien stehen.

Dem Compiler ist es egal, aber dem Builder vom Studio nicht. Wenn das 
File nicht auf .c endet, dann wird ein ungeeignetes Makefile erzeugt und 
der Compiler falsch aufgerufen:
1
./%.o: .././%.c
2
  @echo Building file: $<
3
  @echo Invoking: AVR/GNU C Compiler
4
  $(QUOTE)$(AVR_APP_PATH)avr-gcc.exe$(QUOTE) -funsigned-char -funsigned-bitfields -O0 -fpack-struct -fshort-enums -g3 -Wall -c -std=gnu99 -x c++  -mmcu=atmega16   -MD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
5
  @echo Finished building: $<
6

7
./%.o: .././%.cpp
8
  @echo Building file: $<
9
  @echo Invoking: AVR/GNU CPP Compiler
10
  $(QUOTE)$(AVR_APP_PATH)avr-g++.exe$(QUOTE)   -MD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
11
  @echo Finished building: $<

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren