Estoy experimentando choques extraños. Y me pregunto si es un error en mi código o en el compilador. Cuando compilo el siguiente código C++ con Microsoft Visual Studio 2010 como una versión de lanzamiento optimizado, se estrella en la línea marcada:Fallo en el código C++ debido a un comportamiento indefinido o error del compilador?
struct tup { int x; int y; };
class C
{
public:
struct tup* p;
struct tup* operator--() { return --p; }
struct tup* operator++(int) { return p++; }
virtual void Reset() { p = 0;}
};
int main()
{
C c;
volatile int x = 0;
struct tup v1;
struct tup v2 = {0, x};
c.p = &v1;
(*(c++)) = v2;
struct tup i = (*(--c)); // crash! (dereferencing a NULL-pointer)
return i.x;
}
Mirando hacia el desmontaje, es obvio que debe bloquearse:
int _tmain(int argc, _TCHAR* argv[])
{
00CE1000 push ebp
00CE1001 mov ebp,esp
00CE1003 sub esp,0Ch
C c;
volatile int x = 0;
00CE1006 xor eax,eax
00CE1008 mov dword ptr [x],eax
struct tup v1;
struct tup v2 = {0, x};
00CE100B mov ecx,dword ptr [x]
c.p = &v1;
(*(c++)) = v2;
00CE100E mov dword ptr [ebp-8],ecx
struct tup i = (*(--c));
00CE1011 mov ecx,dword ptr [x]
00CE1014 mov dword ptr [v1],eax
00CE1017 mov eax,dword ptr [ecx]
00CE1019 mov ecx,dword ptr [ecx+4]
00CE101C mov dword ptr [ebp-8],ecx
return i.x;
}
00CE101F mov esp,ebp
00CE1021 pop ebp
00CE1022 ret
En el desplazamiento 00CE1008, escribe un 0 en x.
en el offset 00CE100B se lee x (el 0) en ecx
en el offset 00CE1017 que elimina referencias que 0-puntero.
Veo dos razones posibles:
O hay algún caso sutiles (o no tan sutil?) De un comportamiento indefinido en mi código y el compilador "optimiza" este comportamiento no definido en un accidente.
o hay un error del compilador
¿Alguien ve lo que podría causar el problema?
Gracias,
Jonas
EDIT: Para hacer frente a los comentarios relativos a "puntero a la ubicación no válida"
Si cambio v1
ser struct tup v1[10];
y establecer c.p = &v1[0];
, entonces habrá sin puntero a una ubicación no válida. Pero todavía puedo observar el mismo comportamiento. El desmontaje parece marginalmente diferente, pero todavía hay un bloqueo y sigue causando la carga de 0 en ecx y la desreferenciación.
EDIT: Conclusión
Por lo tanto, probablemente es un error. Me di cuenta de que el accidente se desvanece si cambio
struct tup* operator--() { return --p; }
a
struct tup* operator--() { --p; return p; }
Como bames53 nos dice, el accidente no se produce en VS2011 y concluye que debe haber sido fijada.
nontheless, que decidió presentar ese error por dos razones:
El error todavía podría estar presente en VS2011. Tal vez el optimizador simplemente ha cambiado de una manera que mi código ya no dispara el error.(El error parece ser muy sutil, que no se produce cuando se quita la
volative
o lavirtual void Reset()
)Quiero saber si mi solución es un método confiable para descartar los accidentes, o si los cambios de código en otros lugares pueden reintroducir el error.
Aquí está el enlace:
https://connect.microsoft.com/VisualStudio/feedback/details/741628/error-in-code-generation-for-x86
Estás confundiendo a tantas personas ... Parece un error de compilación para mí. Debería contactarlos en Microsoft Connect. – Blindy
@cambiando 'v2' a' {0, 0}; 'y eliminando' volatile int x' muestra el mismo comportamiento, por lo que no está relacionado. –
@ildjarn: bames53 confirma que ya se ha corregido en vs11. –