【发布时间】:2012-06-29 11:04:03
【问题描述】:
环境:Microsoft Visual Studio 2010 SP1 Preminum(10.0.40219.1 SP1Rel),Windows XP SP3
VC10 编译器支持 auto 关键字,但推断的类型相关信息似乎并不总是正确的枚举。
示例:
#include <type_traits>
enum fruit_t
{
apple = 100,
banana = 200,
};
int main()
{
const auto pa = new auto(banana);
const auto pb = new fruit_t(banana);
static_assert(std::is_same<decltype(pa), decltype(pb)>::value, "not same!");
delete pb;
delete pa;
}
上面的代码应该没有编译时错误或运行时错误。但令我惊讶的是,它编译正常,没有任何错误或警告,但运行不正确。退出主函数后调试器告诉:
检测到堆损坏:在 0x00034878 的 %hs 块 (#55) 之后。 CRT 检测到应用程序在堆缓冲区结束后写入内存。
所以我猜编译器可能在“自动”类型推导中存在错误。下面的汇编器窗口显示,第一个“operator new”调用中请求的内存大小为 1 个字节,而第二个“operator new”调用为 4 个字节。这表明编译器在推导类型的大小上犯了很大的错误。
您认为这是编译器错误吗? Microsoft 是否有任何错误修复?
int main()
{
004113C0 push ebp
004113C1 mov ebp,esp
004113C3 sub esp,10Ch
004113C9 push ebx
004113CA push esi
004113CB push edi
004113CC lea edi,[ebp-10Ch]
004113D2 mov ecx,43h
004113D7 mov eax,0CCCCCCCCh
004113DC rep stos dword ptr es:[edi]
const auto pa = new auto(banana);
004113DE push 1
004113E0 call operator new (411181h)
004113E5 add esp,4
004113E8 mov dword ptr [ebp-104h],eax
004113EE cmp dword ptr [ebp-104h],0
004113F5 je main+51h (411411h)
004113F7 mov eax,dword ptr [ebp-104h]
004113FD mov dword ptr [eax],0C8h
00411403 mov ecx,dword ptr [ebp-104h]
00411409 mov dword ptr [ebp-10Ch],ecx
0041140F jmp main+5Bh (41141Bh)
00411411 mov dword ptr [ebp-10Ch],0
0041141B mov edx,dword ptr [ebp-10Ch]
00411421 mov dword ptr [pa],edx
const auto pb = new fruit_t(banana);
00411424 push 4
00411426 call operator new (411181h)
0041142B add esp,4
0041142E mov dword ptr [ebp-0F8h],eax
00411434 cmp dword ptr [ebp-0F8h],0
0041143B je main+97h (411457h)
0041143D mov eax,dword ptr [ebp-0F8h]
00411443 mov dword ptr [eax],0C8h
00411449 mov ecx,dword ptr [ebp-0F8h]
0041144F mov dword ptr [ebp-10Ch],ecx
00411455 jmp main+0A1h (411461h)
00411457 mov dword ptr [ebp-10Ch],0
00411461 mov edx,dword ptr [ebp-10Ch]
00411467 mov dword ptr [pb],edx
static_assert(std::is_same<decltype(pa), decltype(pb)>::value, "not same!");
delete pb;
0041146A mov eax,dword ptr [pb]
0041146D mov dword ptr [ebp-0ECh],eax
00411473 mov ecx,dword ptr [ebp-0ECh]
00411479 push ecx
0041147A call operator delete (411087h)
0041147F add esp,4
delete pa;
00411482 mov eax,dword ptr [pa]
00411485 mov dword ptr [ebp-0E0h],eax
0041148B mov ecx,dword ptr [ebp-0E0h]
00411491 push ecx
00411492 call operator delete (411087h)
00411497 add esp,4
}
【问题讨论】:
-
在调试器中
pa的类型是什么? -
调试器显示:banana 0x000000c8 int; pa 0x000329d8fruit_t * 常量; pb 0x00032a18fruit_t * 常量。糟糕的是,它表明 'banana' 是 'int' 类型(不是 'fruit_t')。据我所知,VC10的调试器有很多bug,所以上面显示的类型信息很可疑。
-
尽管我的调试器 VS2010 显示了正确的类型 (fruit*),但它在自动分配的那些上崩溃。
-
我的猜测是 auto 在该语法中不起作用(您正在尝试创建一个可以是 int 或 fruit 的香蕉类型 auto),因为表达式
auto x = auto(banana);将显示。你可以做的是decltype(banana)(banana),但这并不漂亮。 -
C++11 标准有示例代码
auto x = new auto(’a’);,第 5.3.4 节第 2 节。所以我认为它也可以在枚举中使用。
标签: c++ visual-c++ enums c++11 auto