C ++ constructor and compiler automatically generate code traps, constructor Compiler

Source: Internet
Author: User

C ++ constructor and compiler automatically generate code traps, constructor Compiler

Recently debug various access violation projects, which are representative and can be solved by standard code standards.

The problem can be summarized into the following code:

 1 class TestString 2 { 3 public: 4     TestString(const char* input) : m_value(input) {} 5     TestString(const TestString& input) : m_value(input.m_value) {} 6     operator const char*() const { return m_value.c_str(); } 7     string m_value; 8 }; 9 10 void main()11 {12     TestString testStr("StringA");13     const char* stringB = "StringB";14     const char* result = true ? testStr : stringB;15     // Will result point to  "StringA"?16     assert(result == testStr.m_value.c_str());17 }

In the above code, you can think that 'result' will point to 'teststr. m_value.c_str () ', because we reload 'operator const char *()',

Otherwise, if you run the above Code, you will find that 'result' points to a random memory address.

After I have ruled out that there are no problems around it, I opened the compilation code browser:

    const char* result = true ? testStr : stringB;00CE9585  mov         eax,1  00CE958A  test        eax,eax  00CE958C  je          main+0B0h (0CE95D0h)  00CE958E  lea         ecx,[testStr]  00CE9591  push        ecx  00CE9592  lea         ecx,[ebp-138h]  00CE9598  call        TestString::TestString (0CE1659h)  ...00CE95DA  call        TestString::TestString (0CE14DDh)  ...00CE9625  call        TestString::operator char const * (0CE105Ah)  ...00CE964C  call        TestString::~TestString (0CE14A1h)  ...00CE9670  call        TestString::~TestString (0CE14A1h)  

Here, you can clearly see that the compiler has replaced 'teststr' and 'stringb' with temporary objects of the 'teststring' type, and then calls 'operator const char *() 'Come on, the result is converted to 'const char * ', but these two temporary objects are automatically destroyed, so the result you get becomes Dangling pointer.

As for the solution, you may think of the following changes:

    const char* result = true ? testStr.m_value.c_str() : stringB;0008504C  mov         eax,1  00085051  test        eax,eax  00085053  je          main+55h (085065h)  00085055  lea         ecx,[testStr]  00085058  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::c_str (081370h)  0008505D  mov         dword ptr [ebp-104h],eax  00085063  jmp         main+5Eh (08506Eh)  00085065  mov         ecx,dword ptr [stringB]  00085068  mov         dword ptr [ebp-104h],ecx  0008506E  mov         edx,dword ptr [ebp-104h]  00085074  mov         dword ptr [result],edx  

You can explicitly call 'test. m_value (). c_str () 'to prevent the compiler from generating unexpected type conversions.

However, as I mentioned earlier in this article, this problem can be avoided through good code specifications. here we need to use 'explicit '. By defining a constructor with a parameter as 'explicit', we can avoid implicit calls by the compiler to the labeled constructor.

So the fix I suggest here is to define your TestString as follows:

class TestString{public:    explicit TestString(const char* input) : m_value(input) {}    explicit TestString(const TestString& input) : m_value(input.m_value) {}    operator const char*() const { return m_value.c_str(); }    string m_value;};

Then let's take a look at the new code generated by the compiler:

    const char* result = true ? testStr : stringB;00F23C3B  mov         eax,1  00F23C40  test        eax,eax  00F23C42  je          main+74h (0F23C54h)  00F23C44  lea         ecx,[testStr]  00F23C47  call        TestString::operator char const * (0F21604h)  00F23C4C  mov         dword ptr [ebp-110h],eax  00F23C52  jmp         main+7Dh (0F23C5Dh)  00F23C54  mov         ecx,dword ptr [stringB]  00F23C57  mov         dword ptr [ebp-110h],ecx  00F23C5D  mov         edx,dword ptr [ebp-110h]  00F23C63  mov         dword ptr [result],edx  

Case close .:)

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.