Код (Text): #include <string> template <class T> T main() { return T(); } void foo() { static_cast<std::string (*)()>(&main); } При выходе из main прога падает. Судя по всему при линковке с майном не проверяется тип возвращаемого значения.
Ого. Никогда бы не подумали, что это слинкуется. Похоже, для символа "main" сделаны некие исключения, поскольку в объектнике имя этой функции не заманглилось и имеет вид "_main". Падение, кстати, происходит не при выходе, а при вызове конструктора: Код (Text): 0:000> u . test!main [c:\users\mal\desktop\test.cpp @ 5]: 004010b0 push ebp 004010b1 mov ebp,esp 004010b3 mov ecx,dword ptr [ebp+8] 004010b6 call test!ILT+5(??0?$basic_stringDU?$char_traitsDstdV?$allocatorD (0040100a) 004010bb mov eax,dword ptr [ebp+8] 004010be pop ebp 004010bf ret 0:000> g (cc0.9b0): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00000000 ebx=7efde000 ecx=00000001 edx=0008e3b8 esi=00000000 edi=00000000 eip=0040116d esp=0018ff18 ebp=0018ff20 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246 test!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy+0x5d: 0040116d mov dword ptr [ecx+18h],0Fh ds:002b:00000019=???????? 0:000> k # ChildEBP RetAddr 00 0018ff20 004010f5 test!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy+0x5d 01 0018ff38 004010bb test!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> >+0x25 02 0018ff40 0040158b test!main+0xb 03 0018ff88 772c3677 test!__tmainCRTStartup+0xfb 04 0018ff94 77d39d72 kernel32!BaseThreadInitThunk+0xe 05 0018ffd4 77d39d45 ntdll!__RtlUserThreadStart+0x70 06 0018ffec 00000000 ntdll!_RtlUserThreadStart+0x1b Хотя можно допустить, что при определённых данных на стеке падение произойдёт где-нибудь в crt после выхода.
Падает из-за несоотвествия конвенции вызова. В данном случае подмена типа возращаемого значения вовсе не безобидна - возврат структуры string выполняется не через регистры, а через неявный аргумент-указатель.
>на вскидку стеку пипец..... Это не стеку пипец – это вызывается конструктор для стринга, расположенного по адресу "1". Как заметил green, возврат стринга выполняется через неявный аргумент – т.е. в данном случае самый первый аргумент функции main расценивается как адрес, по которому нужно создать структуру. CRT же первым аргументом для main делает количество аргументов (int argc). Таким образом, если вызвать программу с $10000 параметров, то, теоретически, она не упадёт ;p