Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   
Forentreff 2012     
Bücher-Shop mit Amazon (Buchkategorien)C++ : Referenzen zu C++ : C++ Builder : Visual C++ : C# : Java : Spieleprogrammierung : Systemprogrammierung Linux : Software-Entwicklung : .NET : Compilertechnik : Algorithmen & Datenstrukturen : Objektorientierung : Entwurfsmuster : UML : eXtreme Programming : Scrum : Projektmanagement : Software-Testing : Datenbanken : Tom DeMarco : Dilbert : User Friendly
C/C++ Forum :: C++ (auch C++0x und C++11) ::  Template-Methode mit Default-Parameter     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/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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:
}
C/C++ Code:
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:
}
C/C++ Code:
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.
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.
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: 6824
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: 6824
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/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
}
C/C++ Code:
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;
}
C/C++ Code:
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
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
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
Code:
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
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/C++ Code:
foo.bar(2.0);
C/C++ Code:
foo.bar(2.0);
C/C++ Code:
foo.bar(2.0);

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

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

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6824
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: 9700
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
Code:
$ ./a.out
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
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.
Nexus
Mitglied

Benutzerprofil
Anmeldungsdatum: 16.05.2006
Beiträge: 9700
Beitrag Nexus Mitglied 17:40:05 10.02.2011   Titel:              Zitieren

drakon schrieb:
Jemand hier, der GCC installiert hat?
Mit g++ 4.5.0 kommt die erwartete Ausgabe (kein Laufzeitfehler):
Code:
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Code:
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Code:
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
SeppJ
Moderator

Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 13604
Beitrag SeppJ Moderator 17:41:01 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?
Ja. Läuft hervorrragend mit GNU und Intel-Compiler (beide ziemlich neu). Debugger meldet auch nichts verdächtiges. Und ich sehe auch keinen Fehler im Code.


Zuletzt bearbeitet von SeppJ am 17:41:19 10.02.2011, insgesamt 1-mal bearbeitet
lkjjkl
Unregistrierter




Beitrag lkjjkl Unregistrierter 17:45:11 10.02.2011   Titel:              Zitieren

Zitat:
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)

Zitat:
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
Value: 2 Step: 0
drakon
Mitglied

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6824
Beitrag drakon Mitglied 17:46:51 10.02.2011   Titel:              Zitieren

Kannst du mir mal den generierten Assembler Code für die beiden Funktionen und die main geben? (EDIT: Ohne die Ausgaben, wens geht. :))
C/C++ Code:
    ForceBug foo;
    foo.bar(2);
    foo.bar(2.0);
C/C++ Code:
ForceBug foo;
foo.bar(2);
foo.bar(2.0);
C/C++ Code:
    ForceBug foo;
    foo.bar(2);
    foo.bar(2.0);

in der main reicht schon, um den Fehler zu erzeugen.

Notiz an mich:
Ich muss mal meine Ubuntu Installation brauchbar machen.. :D

_________________
Blog: www.drakon.ch


Zuletzt bearbeitet von drakon am 17:47:38 10.02.2011, insgesamt 1-mal bearbeitet
SeppJ
Moderator

Benutzerprofil
Anmeldungsdatum: 10.06.2008
Beiträge: 13604
Beitrag SeppJ Moderator 18:14:49 10.02.2011   Titel:              Zitieren

drakon schrieb:
Kannst du mir mal den generierten Assembler Code für die beiden Funktionen und die main geben? (EDIT: Ohne die Ausgaben, wens geht. :))
Meinst du mich? Ok, hier der Code der unoptimierten Version, weil die optimierte Version total unleserlich ist (GCC 4.4.3, 64 Bit):
main:
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
    leaq    -1(%rbp), %rax
    movl    $0, %edx
    movl    $2, %esi
    movq    %rax, %rdi
    call    _ZN8ForceBug3barIiEEvT_S1_

    movsd    .LC0(%rip), %xmm0
    leaq    -1(%rbp), %rax
    xorpd    %xmm1, %xmm1
    movq    %rax, %rdi
    call    _ZN8ForceBug3barIdEEvT_S1_
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
leaq -1(%rbp), %rax
movl $0, %edx
movl $2, %esi
movq %rax, %rdi
call _ZN8ForceBug3barIiEEvT_S1_

movsd .LC0(%rip), %xmm0
leaq -1(%rbp), %rax
xorpd %xmm1, %xmm1
movq %rax, %rdi
call _ZN8ForceBug3barIdEEvT_S1_
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
    leaq    -1(%rbp), %rax
    movl    $0, %edx
    movl    $2, %esi
    movq    %rax, %rdi
    call    _ZN8ForceBug3barIiEEvT_S1_

    movsd    .LC0(%rip), %xmm0
    leaq    -1(%rbp), %rax
    xorpd    %xmm1, %xmm1
    movq    %rax, %rdi
    call    _ZN8ForceBug3barIdEEvT_S1_

_ZN8ForceBug3barIiEEvT_S1_:
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    pushq    %rbp
    movq    %rsp, %rbp
    subq    $32, %rsp
    movq    %rdi, -24(%rbp)
    movl    %esi, -28(%rbp)
    movl    %edx, -32(%rbp)
    movl    -32(%rbp), %eax
    movl    %eax, -4(%rbp)
    movl    $.LC2, %esi
    movl    $_ZSt4cout, %edi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    -28(%rbp), %edx
    movl    %edx, %esi
    movq    %rax, %rdi
    call    _ZNSolsEi
    movl    $.LC3, %esi
    movq    %rax, %rdi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    -32(%rbp), %edx
    movl    %edx, %esi
    movq    %rax, %rdi
    call    _ZNSolsEi
    movl    $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
    movq    %rax, %rdi
    call    _ZNSolsEPFRSoS_E
    leave
    ret
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movq %rdi, -24(%rbp)
movl %esi, -28(%rbp)
movl %edx, -32(%rbp)
movl -32(%rbp), %eax
movl %eax, -4(%rbp)
movl $.LC2, %esi
movl $_ZSt4cout, %edi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl -28(%rbp), %edx
movl %edx, %esi
movq %rax, %rdi
call _ZNSolsEi
movl $.LC3, %esi
movq %rax, %rdi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl -32(%rbp), %edx
movl %edx, %esi
movq %rax, %rdi
call _ZNSolsEi
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
movq %rax, %rdi
call _ZNSolsEPFRSoS_E
leave
ret
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    pushq    %rbp
    movq    %rsp, %rbp
    subq    $32, %rsp
    movq    %rdi, -24(%rbp)
    movl    %esi, -28(%rbp)
    movl    %edx, -32(%rbp)
    movl    -32(%rbp), %eax
    movl    %eax, -4(%rbp)
    movl    $.LC2, %esi
    movl    $_ZSt4cout, %edi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    -28(%rbp), %edx
    movl    %edx, %esi
    movq    %rax, %rdi
    call    _ZNSolsEi
    movl    $.LC3, %esi
    movq    %rax, %rdi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movl    -32(%rbp), %edx
    movl    %edx, %esi
    movq    %rax, %rdi
    call    _ZNSolsEi
    movl    $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
    movq    %rax, %rdi
    call    _ZNSolsEPFRSoS_E
    leave
    ret
Und die andere für double:
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    pushq    %rbp
    movq    %rsp, %rbp
    subq    $48, %rsp
    movq    %rdi, -24(%rbp)
    movsd    %xmm0, -32(%rbp)
    movsd    %xmm1, -40(%rbp)
    movq    -40(%rbp), %rax
    movq    %rax, -8(%rbp)
    movl    $.LC2, %esi
    movl    $_ZSt4cout, %edi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movsd    -32(%rbp), %xmm0
    movq    %rax, %rdi
    call    _ZNSolsEd
    movl    $.LC3, %esi
    movq    %rax, %rdi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movsd    -40(%rbp), %xmm0
    movq    %rax, %rdi
    call    _ZNSolsEd
    movl    $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
    movq    %rax, %rdi
    call    _ZNSolsEPFRSoS_E
    leave
    ret
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
pushq %rbp
movq %rsp, %rbp
subq $48, %rsp
movq %rdi, -24(%rbp)
movsd %xmm0, -32(%rbp)
movsd %xmm1, -40(%rbp)
movq -40(%rbp), %rax
movq %rax, -8(%rbp)
movl $.LC2, %esi
movl $_ZSt4cout, %edi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movsd -32(%rbp), %xmm0
movq %rax, %rdi
call _ZNSolsEd
movl $.LC3, %esi
movq %rax, %rdi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movsd -40(%rbp), %xmm0
movq %rax, %rdi
call _ZNSolsEd
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
movq %rax, %rdi
call _ZNSolsEPFRSoS_E
leave
ret
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    pushq    %rbp
    movq    %rsp, %rbp
    subq    $48, %rsp
    movq    %rdi, -24(%rbp)
    movsd    %xmm0, -32(%rbp)
    movsd    %xmm1, -40(%rbp)
    movq    -40(%rbp), %rax
    movq    %rax, -8(%rbp)
    movl    $.LC2, %esi
    movl    $_ZSt4cout, %edi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movsd    -32(%rbp), %xmm0
    movq    %rax, %rdi
    call    _ZNSolsEd
    movl    $.LC3, %esi
    movq    %rax, %rdi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
    movsd    -40(%rbp), %xmm0
    movq    %rax, %rdi
    call    _ZNSolsEd
    movl    $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
    movq    %rax, %rdi
    call    _ZNSolsEPFRSoS_E
    leave
    ret

Debuginformationen habe ich mal rausgekürzt um es übersichtlicher zu halten. Ich weiß jetzt aber nicht, was das bringen soll, beide Funktionen arbeiten korrekt und sind im Prinzip identisch, außer dass bei der einen alle Befehle für int sind, bei der anderen für doubles. Wie sehen die Funktionen denn bei VS 2010 aus?

edit: Oh, die Ausgabefunktionen habe ich entgegen deinem Wunsch noch drin. Naja, so lang ist's ja nun auch nicht.


Zuletzt bearbeitet von SeppJ am 18:17:11 10.02.2011, insgesamt 3-mal bearbeitet
drakon
Mitglied

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6824
Beitrag drakon Mitglied 18:27:23 10.02.2011   Titel:              Zitieren

Hmm. Mir scheint als hätte ich den Fehler gefunden, den VC da macht.
Die Funktionen selbst sind denke ich korrekt implementiert, aber der Aufruf der Funktionen scheint nicht so ganz zu klappen.

Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
    foo.bar(2);
00EA10AB  push        0  % zweiter parameter: ok
00EA10AD  push        2  % erster parameter: ok
00EA10AF  lea         ecx,[foo]  % this: ok
00EA10B2  call        ForceBug::bar<int> (0EA1046h)  
    foo.bar(2.0);
00EA10B7  push        0  % (1)
00EA10B9  sub         esp,8  
00EA10BC  fld         qword ptr [__real@4000000000000000 (0EA6830h)]  % parameter 1
00EA10C2  fstp        qword ptr [esp]  % parameter 1 speichern
00EA10C5  lea         ecx,[foo]  % this
00EA10C8  call        ForceBug::bar<double> (0EA103Ch)
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
foo.bar(2);
00EA10AB push 0 % zweiter parameter: ok
00EA10AD push 2 % erster parameter: ok
00EA10AF lea ecx,[foo] % this: ok
00EA10B2 call ForceBug::bar<int> (0EA1046h)
foo.bar(2.0);
00EA10B7 push 0 % (1)
00EA10B9 sub esp,8
00EA10BC fld qword ptr [__real@4000000000000000 (0EA6830h)] % parameter 1
00EA10C2 fstp qword ptr [esp] % parameter 1 speichern
00EA10C5 lea ecx,[foo] % this
00EA10C8 call ForceBug::bar<double> (0EA103Ch)
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
    foo.bar(2);
00EA10AB  push        0  % zweiter parameter: ok
00EA10AD  push        2  % erster parameter: ok
00EA10AF  lea         ecx,[foo]  % this: ok
00EA10B2  call        ForceBug::bar<int> (0EA1046h)  
    foo.bar(2.0);
00EA10B7  push        0  % (1)
00EA10B9  sub         esp,8  
00EA10BC  fld         qword ptr [__real@4000000000000000 (0EA6830h)]  % parameter 1
00EA10C2  fstp        qword ptr [esp]  % parameter 1 speichern
00EA10C5  lea         ecx,[foo]  % this
00EA10C8  call        ForceBug::bar<double> (0EA103Ch)

Da sieht man, dass bar(2) korrekt aufgerufen wird. Jedoch bin ich bei (1) stutzig geworden. Warum wird da lediglich ein Wort gepusht und nicht 2, wie es bei einem double ja sein müsste?

Also habe ich das ganze mal umgedreht:
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    foo.bar(2.0);
00EE10AB  sub         esp,8  
00EE10AE  fldz  % schon eher wenn man floats ausnullen will
00EE10B0  fstp        qword ptr [esp]  
00EE10B3  sub         esp,8  
00EE10B6  fld         qword ptr [__real@4000000000000000 (0EE6830h)]  
00EE10BC  fstp        qword ptr [esp]  
00EE10BF  lea         ecx,[foo]  
00EE10C2  call        ForceBug::bar<double> (0EE103Ch)  
    foo.bar(2);
00EE10C7  sub         esp,8  
00EE10CA  fldz  % (2)
00EE10CC  fstp        qword ptr [esp]  
00EE10CF  push        2  % erster parameter
00EE10D1  lea         ecx,[foo]  
00EE10D4  call        ForceBug::bar<int> (0EE1046h)  
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
foo.bar(2.0);
00EE10AB sub esp,8
00EE10AE fldz % schon eher wenn man floats ausnullen will
00EE10B0 fstp qword ptr [esp]
00EE10B3 sub esp,8
00EE10B6 fld qword ptr [__real@4000000000000000 (0EE6830h)]
00EE10BC fstp qword ptr [esp]
00EE10BF lea ecx,[foo]
00EE10C2 call ForceBug::bar<double> (0EE103Ch)
foo.bar(2);
00EE10C7 sub esp,8
00EE10CA fldz % (2)
00EE10CC fstp qword ptr [esp]
00EE10CF push 2 % erster parameter
00EE10D1 lea ecx,[foo]
00EE10D4 call ForceBug::bar<int> (0EE1046h)
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    foo.bar(2.0);
00EE10AB  sub         esp,8  
00EE10AE  fldz  % schon eher wenn man floats ausnullen will
00EE10B0  fstp        qword ptr [esp]  
00EE10B3  sub         esp,8  
00EE10B6  fld         qword ptr [__real@4000000000000000 (0EE6830h)]  
00EE10BC  fstp        qword ptr [esp]  
00EE10BF  lea         ecx,[foo]  
00EE10C2  call        ForceBug::bar<double> (0EE103Ch)  
    foo.bar(2);
00EE10C7  sub         esp,8  
00EE10CA  fldz  % (2)
00EE10CC  fstp        qword ptr [esp]  
00EE10CF  push        2  % erster parameter
00EE10D1  lea         ecx,[foo]  
00EE10D4  call        ForceBug::bar<int> (0EE1046h)  

Bei (2) dachte ich dann nur WTF? - Warum wird da eine floating Point Operation gemacht, wenn doch nur int's im Spiel sind?

Da scheint irgendwie Code vorschnell erzeugt zu werden.. Ok, also mal schauen was passiert, wenn wir die bösen templates weglassen. :
(ich habe das template mit identischen Funktionen mit expliziten Parametern ausgetauscht)
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    foo.bar(2.0);
00C6168B  sub         esp,8  
00C6168E  fldz  
00C61690  fstp        qword ptr [esp]  
00C61693  sub         esp,8  
00C61696  fld         qword ptr [__real@4000000000000000 (0C66830h)]  
00C6169C  fstp        qword ptr [esp]  
00C6169F  lea         ecx,[foo]  
00C616A2  call        ForceBug::bar (0C61050h)  
    foo.bar(2);
00C616A7  push        0  % kein floating Zeugs mehr.
00C616A9  push        2  
00C616AB  lea         ecx,[foo]  
00C616AE  call        ForceBug::bar (0C6104Bh)
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
foo.bar(2.0);
00C6168B sub esp,8
00C6168E fldz
00C61690 fstp qword ptr [esp]
00C61693 sub esp,8
00C61696 fld qword ptr [__real@4000000000000000 (0C66830h)]
00C6169C fstp qword ptr [esp]
00C6169F lea ecx,[foo]
00C616A2 call ForceBug::bar (0C61050h)
foo.bar(2);
00C616A7 push 0 % kein floating Zeugs mehr.
00C616A9 push 2
00C616AB lea ecx,[foo]
00C616AE call ForceBug::bar (0C6104Bh)
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    foo.bar(2.0);
00C6168B  sub         esp,8  
00C6168E  fldz  
00C61690  fstp        qword ptr [esp]  
00C61693  sub         esp,8  
00C61696  fld         qword ptr [__real@4000000000000000 (0C66830h)]  
00C6169C  fstp        qword ptr [esp]  
00C6169F  lea         ecx,[foo]  
00C616A2  call        ForceBug::bar (0C61050h)  
    foo.bar(2);
00C616A7  push        0  % kein floating Zeugs mehr.
00C616A9  push        2  
00C616AB  lea         ecx,[foo]  
00C616AE  call        ForceBug::bar (0C6104Bh)

ahh.. schon eher..

und andersrum:
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    foo.bar(2);
008A168B  push        0  
008A168D  push        2  
008A168F  lea         ecx,[foo]  
008A1692  call        ForceBug::bar (8A104Bh)  
    foo.bar(2.0);
008A1697  sub         esp,8  
008A169A  fldz  % jetzt passt auch das hier
008A169C  fstp        qword ptr [esp]  
008A169F  sub         esp,8  
008A16A2  fld         qword ptr [__real@4000000000000000 (8A6830h)]  
008A16A8  fstp        qword ptr [esp]  
008A16AB  lea         ecx,[foo]  
008A16AE  call        ForceBug::bar (8A1050h)  
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
foo.bar(2);
008A168B push 0
008A168D push 2
008A168F lea ecx,[foo]
008A1692 call ForceBug::bar (8A104Bh)
foo.bar(2.0);
008A1697 sub esp,8
008A169A fldz % jetzt passt auch das hier
008A169C fstp qword ptr [esp]
008A169F sub esp,8
008A16A2 fld qword ptr [__real@4000000000000000 (8A6830h)]
008A16A8 fstp qword ptr [esp]
008A16AB lea ecx,[foo]
008A16AE call ForceBug::bar (8A1050h)
Assembler Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    foo.bar(2);
008A168B  push        0  
008A168D  push        2  
008A168F  lea         ecx,[foo]  
008A1692  call        ForceBug::bar (8A104Bh)  
    foo.bar(2.0);
008A1697  sub         esp,8  
008A169A  fldz  % jetzt passt auch das hier
008A169C  fstp        qword ptr [esp]  
008A169F  sub         esp,8  
008A16A2  fld         qword ptr [__real@4000000000000000 (8A6830h)]  
008A16A8  fstp        qword ptr [esp]  
008A16AB  lea         ecx,[foo]  
008A16AE  call        ForceBug::bar (8A1050h)  

Jetzt stimmts auch in der Richtung.

Fazit: Selbst VC++ 2010 hat gewisse Probleme mit templates.. :P

@SeppJ:
Danke, aber ich hab den Fehler, den VC da macht bereits. :)

Hat jemand eine Ahnung, ob der Bug bereits gemeldet wurde? Respektive wo es da eine gute DB dazu gibt? Ich werde das bei Gelegenheit mal noch in meinem Blog posten. Wird Zeit, dass da wiedermal was passiert. :)

//EDIT:
Habe anscheinend den korrekten Anlaufpunkt gefunden und der Fehler scheint noch nicht bekannt zu sein:
https://connect.microsoft.com/VisualStudio/Feedback

_________________
Blog: www.drakon.ch


Zuletzt bearbeitet von drakon am 18:45:46 10.02.2011, insgesamt 2-mal bearbeitet
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 13529
Beitrag hustbaer Mitglied 21:56:22 10.02.2011   Titel:              Zitieren

scary...

@drakon: Hast du den Fehler reported?

_________________
"Let there be Licht..." http://lichttools.sourceforge.net/
Sehr cooles ASCII Spiel (leider nicht von mir): ASCII-Scramble - http://www.roskakori.at/ascii/
djohn@work
Unregistrierter




Beitrag djohn@work Unregistrierter 12:07:16 11.02.2011   Titel:              Zitieren

Hallo,

vielen Dank für die vielen Rückmeldungen. Ich hab jetzt hier
den Fehler gemeldet.

djohn
drakon
Mitglied

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6824
Beitrag drakon Mitglied 14:49:38 11.02.2011   Titel:              Zitieren

hustbaer schrieb:
scary...

@drakon: Hast du den Fehler reported?


Nein. Bin gester nicht dazu gekommen. Wollte eigentlich einen exakten Beschreib (auch für meinen Blog) von dem Fehler machen.

Ich habe mich gestern dort extra noch angemeldet. :P

@djohn:
Da ich ja bereits den Fehler analysiert habe wäre es vielleicht gut das auch noch zu melden. Dann können die sich ein wenig Arbeit sparen.. ^^
Ich werde mal in einem Kommentar den Fehlerbeschreib ergänzen.

_________________
Blog: www.drakon.ch
drakon
Mitglied

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6824
Beitrag drakon Mitglied 15:15:08 11.02.2011   Titel:              Zitieren

Habe gerade noch ein paar Sachen ausprobiert. Mit freien template Funktionen funktioniert es und auch wenn man die Definition inline macht (was denke ich der Hauptgrund ist, dass den Fehler noch niemand bemerkt hat).

_________________
Blog: www.drakon.ch
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 13529
Beitrag hustbaer Mitglied 02:49:33 12.02.2011   Titel:              Zitieren

Der Bug tritt mit freien Funktionen genau so auf:

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = NumericType());

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 0
// 4.27698e+086, 1.16762e-307
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = NumericType());

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
NumericType dummy = step;
std::cout << value << ", " << step << std::endl;
}

int main()
{
foobar(2);
foobar(3.14);
return 0;
}

// output:
// 2, 0
// 4.27698e+086, 1.16762e-307
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = NumericType());

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 0
// 4.27698e+086, 1.16762e-307


Scheint aber wirklich davon abhängig zu sein dass Deklaration und Definition getrennt sind. Und ich kann's auch nicht mit etwas anderem als double reproduzieren. Und das auch nur, wenn vorher oder nachher ein Aufruf mit etwas anderem als double erfolgt.

Auch nicht uninteressant folgendes:
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2); // <- hier direkt 2 statt NumericType() (0 oder andere Integer gehen genau so)

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 2
// 4.27698e+086, 3.75217e-308
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2); // <- hier direkt 2 statt NumericType() (0 oder andere Integer gehen genau so)

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
NumericType dummy = step;
std::cout << value << ", " << step << std::endl;
}

int main()
{
foobar(2);
foobar(3.14);
return 0;
}

// output:
// 2, 2
// 4.27698e+086, 3.75217e-308
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2); // <- hier direkt 2 statt NumericType() (0 oder andere Integer gehen genau so)

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 2
// 4.27698e+086, 3.75217e-308

Immer noch (fast) der selbe falsche Output.

Wenn man als Default-Wert allerdings ein double Literal hinschreibt...
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2.71828); // <- jetzt mit double literal hier

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 1949120276
// 3.14, 2.71828
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2.71828); // <- jetzt mit double literal hier

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
NumericType dummy = step;
std::cout << value << ", " << step << std::endl;
}

int main()
{
foobar(2);
foobar(3.14);
return 0;
}

// output:
// 2, 1949120276
// 3.14, 2.71828
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2.71828); // <- jetzt mit double literal hier

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 1949120276
// 3.14, 2.71828

Auch falsch, aber ganz anders falsch :)

_________________
"Let there be Licht..." http://lichttools.sourceforge.net/
Sehr cooles ASCII Spiel (leider nicht von mir): ASCII-Scramble - http://www.roskakori.at/ascii/
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 13529
Beitrag hustbaer Mitglied 03:51:44 12.02.2011   Titel:              Zitieren

Der 64 Bit Compiler scheint übrigens genau so betroffen zu sein.

_________________
"Let there be Licht..." http://lichttools.sourceforge.net/
Sehr cooles ASCII Spiel (leider nicht von mir): ASCII-Scramble - http://www.roskakori.at/ascii/
drakon
Mitglied

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6824
Beitrag drakon Mitglied 12:52:06 12.02.2011   Titel:              Zitieren

hustbaer schrieb:
Der Bug tritt mit freien Funktionen genau so auf:

Ah. Ich habe das nur mit direkt definierten freien Funktionen probiert.

Zitat:
Der 64 Bit Compiler scheint übrigens genau so betroffen zu sein

Assembler Code:
    f.bar(2);
000000013F39165B  xorpd       xmm2,xmm2  
000000013F39165F  mov         edx,2  
Assembler Code:
f.bar(2);
000000013F39165B xorpd xmm2,xmm2
000000013F39165F mov edx,2
Assembler Code:
    f.bar(2);
000000013F39165B  xorpd       xmm2,xmm2  
000000013F39165F  mov         edx,2  

Uh, oh. Ja.. sieht so aus.. ^^
Aber es gibt keinen Laufzeitfehler bei mir.

Scheint wirklich hauptsächlich an der Trennung zu liegen. Zum Glück implementieren die meisten templates direkt. :P

_________________
Blog: www.drakon.ch
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 13529
Beitrag hustbaer Mitglied 00:57:35 13.02.2011   Titel:              Zitieren

Tjaaah... die meisten.

In einem grösseren Projekt das ich gerade entwickle (mit VC 2005) hab' ich *einige* Templates mit getrennter Deklaration und Definition. Zwecks übersichtlichkeit der Header Files (Definition steht in eigenen .inl Files).
Und auch mit Default-Parametern und die Variablen sind auch oft vom Typ double :(

EDIT:
Wobei... dort werden eigentlich nur doubles verwendet, und nie was anderes. Sollte dann OK sein. Hab auch noch keinen derartigen Fehler beobachtet. Doof ist es trotzdem. /EDIT

_________________
"Let there be Licht..." http://lichttools.sourceforge.net/
Sehr cooles ASCII Spiel (leider nicht von mir): ASCII-Scramble - http://www.roskakori.at/ascii/


Zuletzt bearbeitet von hustbaer am 01:01:13 13.02.2011, insgesamt 1-mal bearbeitet
DJohn
Mitglied

Benutzerprofil
Anmeldungsdatum: 17.06.2003
Beiträge: 105
Beitrag DJohn Mitglied 10:33:08 13.02.2011   Titel:              Zitieren

@hustbaer

Beim Versuch ein Minimalbeispiel zu erstellen, konnte ich den Fehler bei freien Funktionen auch nicht reproduzieren. Hatte da wahrscheinlich wie drakon noch eine der anderen Bedingungen wegreduziert. Bei Deiner zweiten Variante (Default-Wert ist ein int) reicht es aus, nur eine Template-Instanz mit double zu erzeugen um zumindest bei VS2005 den Fehler zu provozieren. Die zusätzliche Bedingung, dass man mindestens 2 Template-Instanzen mit unterschiedlichen Typen für den Fehler braucht, fällt dann weg.

Ich hatte auch nur wegen der Übersichtlichkeit Deklaration und Definition getrennt, kein großes Problem, dass jetzt zu ändern. Aber wenn so ein Fehler erstmal auftritt, ist man natürlich unsicher, unter welchen Bedingungnen noch dieses undefinierte Verhalten auftreten kann.
Deshalb, nochmal Danke an alle die sich an der Diskussion beteiligt haben, ich denke, wir haben jetzt ganz gut eingegrenzt, wann der Fehler auftritt.

djohn
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 13529
Beitrag hustbaer Mitglied 11:38:20 13.02.2011   Titel:              Zitieren

Noch was lustiges...
Folgendes compiliert mit VS 2010:
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

int g_i = 42;

template<typename T>
void baz(T a1, T* a2 = &g_i); // <- default argument should only work for T = int

template<typename T>
void baz(T a1, T* a2)
{
    std::cout << a1 << ", " << *a2 << std::endl;
}

class c {};

std::ostream& operator << (std::ostream& os, c const&)
{
    return os;
}

int main()
{
    baz(2);
    baz(3.14);   // compiles OK, but should not
    baz("test"); // compiles OK, but should not
    baz(c());    // compiles OK, but should not
    return 0;
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

int g_i = 42;

template<typename T>
void baz(T a1, T* a2 = &g_i); // <- default argument should only work for T = int

template<typename T>
void baz(T a1, T* a2)
{
std::cout << a1 << ", " << *a2 << std::endl;
}

class c {};

std::ostream& operator << (std::ostream& os, c const&)
{
return os;
}

int main()
{
baz(2);
baz(3.14); // compiles OK, but should not
baz("test"); // compiles OK, but should not
baz(c()); // compiles OK, but should not
return 0;
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

int g_i = 42;

template<typename T>
void baz(T a1, T* a2 = &g_i); // <- default argument should only work for T = int

template<typename T>
void baz(T a1, T* a2)
{
    std::cout << a1 << ", " << *a2 << std::endl;
}

class c {};

std::ostream& operator << (std::ostream& os, c const&)
{
    return os;
}

int main()
{
    baz(2);
    baz(3.14);   // compiles OK, but should not
    baz("test"); // compiles OK, but should not
    baz(c());    // compiles OK, but should not
    return 0;
}

Beim Ausführen kommt natürlich nur Mist raus...

:eek: :eek: :eek:

_________________
"Let there be Licht..." http://lichttools.sourceforge.net/
Sehr cooles ASCII Spiel (leider nicht von mir): ASCII-Scramble - http://www.roskakori.at/ascii/


Zuletzt bearbeitet von hustbaer am 11:39:36 13.02.2011, insgesamt 1-mal bearbeitet
C/C++ Forum :: C++ (auch C++0x und C++11) ::  Template-Methode mit Default-Parameter   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, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de 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.