Manage the structure alignment in your c ++ Project

Source: Internet
Author: User

Recently, I upgraded a vc6.0 project to vc2008. I am tired of the cold and old face of vc6 and want to change the freshness. By the way, the project uses the Notes api c library to access emails. Recompile

Not as difficult as you think, it is nothing more than correcting the warning and error in character string conversion. After the compilation is complete, open cppunit to prepare for the test. An error dialog box pops up:

Run-Time check failure #2-stack around the variable 'xxx' was upted.

The error is caused by a string variable, which is an instance of the cnstring class. According to msdn, this object causes stack leakage.

In order to find the cause of the problem, the cnstring is simplified and only the constructor and destructor are retained:Word m_nsize; <br/> char * m_pszdata; <br/> wchar_t * m_pswdata; <br/>... </P> <p> cnstring (Word Size) {<br/> m_nsize = size; <br/> m_pszdata = new char [size]; <br/> m_pswdata = NULL; <br/>}</P> <p> ~ Cnstring () {<br/> Delete [] m_pszdata; <br/> Delete [] m_pswdata; <br/>}< br/>

A simple test was conducted again:

Cnstring STR (200); <br/> STR = _ T ("I love C ++ ");

Run, the error persists. Disable the RTC check of vc2008 and the error disappears. You cannot give up easily. There must be problems. Generally, the stack memory leakage error is caused by out-of-bounds array access. However, my code is a simple new and delete operation. But where is the problem?

I searched Google for a long time and found a free2o article on Security cookie on the csdn blog:

Bytes. After careful consideration and consideration of the assembly code, I found the real cause of the problem.

First, the compiler allocates a 0e4h Size Stack space before the function call, and uses 0cccccccch to fill the stack:

00472aa0 push EBP <br/> 00472aa1 mov EBP, esp <br/> 00472aa3 sub ESP, 0e4h <br/> 00472aa9 push EBX <br/> 00472aaa push ESI <br/> 00472aab push EDI <br/> 00472aac push ECx <br/> 00472aad Lea EDI, [ebp-0E4h] <br/> 00472ab3 mov ECx, 39 h <br/> 00472ab8 mov eax, 0 cccccccch <br/> 00472abd rep STOs dword ptr es: [EDI] </P> <p>

After the function is complete, the compiler checks whether unused stacks are damaged:

00472ad0 Lea ECx, [STR] <br/> 00472ad3 call cnstring ::~ Cnstring (4446c5h) <br/> 00472ad8 push edX <br/> 00472ad9 mov ECx, EBP <br/> 00472adb push eax <br/> 00472adc Lea edX, [(472b00h)] <br/> 00472ae2 call @ ILT + 2235 (@ _ rtc_checkstackvars @ 8) (4428c0h)

The memory for 472b00h stores the _ rtc_framedesc structure content, which stores the address, size, name, and other information of the variables in the stack:

01 00 00 00 08 2B 47 00 E0 FF 0a 00 00 00 14 2B 47 00 73

Note: The above 01 indicates the number of variables, and 0e indicates the size of the variables. Have you found any problems? In my class definition, there are only three member variables: char *, word, and wchar_t *. The default/zp8 alignment mode should be 0 C (12, why is it 0a (10? In this way, when the runtime checks the stack space behind the STR variable, the memory addressing error occurs, and the normal object space is regarded as the unused space for check. Therefore, bang! You won the prize.

With this understanding, I immediately began to check the structure alignment settings in the header file. Finally, the following lines are found in the global. h of notes c api:

# Pragma pack (1)

I remember seeing the data structure packing section in the help of notes c api, But I didn't quite agree with it. This was a complete epiphany.

On machines that use the Intel architecture, data structures passed through the lotus c api for Domino and notes must have the structure members packed on 1-byte boundaries. this saves space in data structures stored on disk, and preserves binary compatibility with previous releases of Domino or notes.

Because I didn't use the lotus API functions that need to pass the structure in the project, add the following in the test Class header file:

# Pragma pack ()

Solve the problem immediately.

Then run another test and find that the XML cannot be loaded again. The prompt "Unrecognized xml header" is always displayed ". XML data is passed in through a structure pointer:

Struct {<br/>... <br/> tchar config [1024] <br/>}

Check that the data in config is correct. What is the problem? Is alignment still a problem?

Add the following command to the CPP for creating structure data and the CPP for loading XML:

# Pragma pack (show)

 

After compilation, we found that the structure alignment of the two CPP is 1 and 8. Originally, the former contains the global. h header file, and the latter does not. If the structure alignment is true, the solution is to define the pack command before and after the structure definition:

 # Pragma pack (8) <br/> struct {<br/>... <br/> tchar config [1024] <br/>}< br/> # pragma pack () <br/>

Solve the problem.

 

 

Related Article

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.