Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   

Die mobilen Seiten von c++.de:
http://m.c-plusplus.de
Infos hier [BETA]

  
c++.de :: C++ (auch C++0x und C++11) ::  Template-Methode mit Default-Parameter  
Gehen Sie zu Seite 1, 2, 3  Weiter
  Zeige alle Beiträge auf einer Seite
Auf Beitrag antworten
Autor Nachricht
djohn@work
Unregistrierter




Beitrag djohn@work Unregistrierter 16:31:53 10.02.2011   Titel:   Template-Methode mit Default-Parameter            Zitieren

Hallo,

Ich habe eine template-Methode erstellt, die einen Default-Parameter verwendet. Durch den Aufruf der Methode zerstöre ich mir den Stack! Allerdings ist mit nicht klar, was hier falsch ist.

Minimalbeispiel:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ForceBug
{
public:
template<typename NumericType>
void bar(NumericType value, NumericType step = NumericType());
};
 
template<typename NumericType>
void ForceBug::bar(NumericType value, NumericType step)
{
    NumericType dummy = step; // Beim 5. Aufruf von foo.bar ist step != 0.0
}
int main()
{
    ForceBug foo;
    foo.bar(2);
    foo.bar(2.0);
    foo.bar(2.0);
    foo.bar(2.0);
    foo.bar(2.0);
    return 0;   // hier kommt vom Debugger die Fehlermeldung:
}

Fehler:
Code:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

Noch ein paar Anmerkungen:
Wenn man den Defaultparamter mit "step=0" definiert, reicht schon ein Aufruf mit einem double-Parameter, um den Fehler zu produzieren. Mit "step=NumericType()" konnte ich es nur reproduzieren, wenn zuerst ein Aufruf mit einem int-Parameter und danach mit einem double-Parameter erfolgt. Der Fehler lässt sich auch nicht bei freien Funktion reproduzieren oder wenn die Methode direkt in der Klasse definiert wird. Ich verwende Visual Studio 2005.

Was mache ich falsch? Falls das ein Compiler-Problem ist, gibt es dazu irgenwo schon einen Fehlerreport? Kann jemand nachvollziehen, ob das Problem in Visual Studio 2008 auch noch besteht?

Danke
djohn
drakon
Mitglied

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6862
Beitrag drakon Mitglied 16:41:35 10.02.2011   Titel:              Zitieren

Das scheint ein Compiler Bug zu sein, denn du machst rein gar nichts, womit du eine Calling Convention missachten könntest. ;)

Unter VS 2010 läuft das ohne Probleme.
VS 2005 hat afaik Probleme mit templates. Kann gut sein, dass es daher kommt, aber mit normalem Code kann man so einen Fehler nicht erzeugen (müsstest z.B inline assembler benutzen oder vlt. mit einem merkwürdigen Pointer hack).

_________________
Blog: www.drakon.ch


Zuletzt bearbeitet von drakon am 16:41:58 10.02.2011, insgesamt 1-mal bearbeitet
fdfdg
Unregistrierter




Beitrag fdfdg Unregistrierter 16:57:47 10.02.2011   Titel:              Zitieren

drakon schrieb:
Unter VS 2010 läuft das ohne Probleme.

Bei mir krachts in der 10er EE im Debug. Release läuft.
drakon
Mitglied

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6862
Beitrag drakon Mitglied 17:19:42 10.02.2011   Titel:              Zitieren

Tatsächlich. Auf Debug krieg ich den Fehler auch. Hatte es aus versehen noch auf Release.

Scheint, dass es Probleme gibt sobald man verschiedene Typen übergibt. Da werden aber korrekt 2 verschiedene Funktionen aufgerufen. Der Fehler scheint von den verschiedenen Grössen der Parameter zu kommen. Aber ich sehe nicht, was an dem Code falsch sein sollte.

Wenn ich x64 Code generieren lasse, dann läufts auch im Debug.

_________________
Blog: www.drakon.ch
djohn@work
Unregistrierter




Beitrag djohn@work Unregistrierter 17:21:24 10.02.2011   Titel:              Zitieren

Ja, das Minimalbeispiel macht im Release nichts sichtbares, deshalb scheint alles in Ordnung. Wenn man aber einfach eine Ausgabe einfügt, sieht man, dass da was nicht stimmen kann:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
class ForceBug
{
public:
template<typename NumericType>
void bar(NumericType value, NumericType step = NumericType());
};
 
template<typename NumericType>
void ForceBug::bar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << "Value: " << value << " Step: " << step << std::endl;
}
int main()
{
    ForceBug foo;
    foo.bar(2);
    foo.bar(2.0);
    foo.bar(2.0);
    foo.bar(2.0);
    foo.bar(2.0);
    return 0;
}

Ausgabe:
Code:
Value: 2 Step: 0
Value: 0 Step: 1.80244e-307
Value: 0 Step: 1.79435e-307
Value: 0 Step: 5.30499e-315
Value: 0 Step: 1.23606e-312

erwartete Ausgabe:
Code:
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0

djohn
vermutung
Unregistrierter




Beitrag vermutung Unregistrierter 17:24:12 10.02.2011   Titel:              Zitieren

C++:
foo.bar(2.0);

Kann es sein, dass du
C++:
foo.bar(2,0);

schreiben wolltest? Denn du erwartest ja 2 Parameter...
drakon
Mitglied

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6862
Beitrag drakon Mitglied 17:34:46 10.02.2011   Titel:              Zitieren

@djohn
Das kommt wahrscheinlich daher, dass bei double irgendwas schief läuft und er irgendwie nicht 2 Wörter liest, sondern so nur ein Teil und dann den Rest von irgend einem anderen Wort liest.

@vermutung
Spielt eigentlich keine Rolle, weil das template 2 Funktionen machen kann. Man kann natürlich beide Parameter angeben, aber das tut ja nichts zur Sache, dass der gezeigte Code einen Fehler generiert.

Ich würde mal vermute, dass hier tatsächlich ein Bug vorliegt. Jemand hier, der GCC installiert hat?

_________________
Blog: www.drakon.ch
djohn@work
Unregistrierter




Beitrag djohn@work Unregistrierter 17:35:44 10.02.2011   Titel:              Zitieren

2.0 ist schon richtig, damit soll eine Template-Instance für doube erzwungen werden. (Kann auch jeder andere double-Wert sein.) Als zweiter Parameter soll automatisch der Default-Parameter genommen werden.

djohn
Nexus
Mitglied

Benutzerprofil
Anmeldungsdatum: 16.05.2006
Beiträge: 10299
Beitrag Nexus Mitglied 17:36:23 10.02.2011   Titel:              Zitieren

Wirklich merkwürdig, bei mir (VS 2010) ist der Fehler ebenfalls reproduzierbar. Ich würde im Microsoft-spezifischen Unterforum nachfragen (oder diesen Thread verschieben), eventuell wissen die dort mehr.

@ vermutung: Kaum, er will halt mit double instanziieren. Der zweite Parameter ist eh ein Default-Parameter.
seldon
Unregistrierter




Beitrag seldon Unregistrierter 17:39:56 10.02.2011   Titel:              Zitieren

drakon schrieb:

Ich würde mal vermute, dass hier tatsächlich ein Bug vorliegt. Jemand hier, der GCC installiert hat?

gcc 4.5.2 verhält sich wie erwartet:
Code:
$ ./a.out
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0

Ich sehe im Code auch keinen Fehler. Scheint ein VS-Bug zu sein.
c++.de :: C++ (auch C++0x und C++11) ::  Template-Methode mit Default-Parameter  
Gehen Sie zu Seite 1, 2, 3  Weiter
Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.