Solution for program crash caused by std: string class in vc ++ STL

Source: Internet
Author: User
Tags string methods tidy

Reference an article translated on the MS Website:
STL std: string class causes crash and memory damage on multi-processor computers
Http://support.microsoft.com/default.aspx? Scid = kb % 3Bzh-cn % 3B813810

Original English:
Http://support.microsoft.com/default.aspx? Scid = kb; en-us; 813810

--------- Abstract --------------
Symptom

Cause

Solution

Method 1: use Microsoft Visual C ++. NET (7.0 and later)

Method 2: Use Microsoft Visual C ++ 6.0 to remove STL from a third party

Alternative Method

Solve the Std: String class problem in Microsoft Visual C ++ 6.0 STL

Disable string reference count

Method 1: use static CRT connections only

Method 2: Use Dynamic CRT Link

Method 3: use smart hackers to avoid link problems

Method 4: Use custom Std: String DLL

More information

Reference

------------------- Body ------------------------------------------------------
Symptom
When you build a Microsoft Visual C ++ 6.0 application using the provided standard template library (STL), Memory Corruption may occur, or the computer may stop responding. These symptoms are more common on a multi-processor computer. The same Code may have been used on a single processor computer without such issues before. When the check error thread is in the debugger, the memory management function usually fails. We often see the basic_string <Char. Button> class method in the stack trace. Memory Corruption also causes symptoms, which are irrelevant to string processing.

Stack tracing is the cause of the crash: 01 0012ebc4 77fb4014 0246ffd0 00000027 02531000 NTDLL! Rtlpdphreportcorruptedblock + 0x8c
02 0012 ebec 77fb2cb1 02531000 01001002 0246ffd0 NTDLL! Rtlpdphnormalheapfree + 0x46
03 0012ec10 77fb5653 02530000 01001002 0246ffd0 NTDLL! Rtlpdebugpageheapfree + 0xa6
04 0012ec88 77fa760a 02530000 01001002 0246ffd0 NTDLL! Rtldebugfreeheap + 0x203
05 0012ed28 77fcba9e 02530000 01001002 0246ffd0 NTDLL! Rtlfreeheapslowly + 0x4d
06 0012 edcc 004065a6 02530000 00000000 0246ffd0 NTDLL! Rtlfreeheap + 0x53
07 0012ee14 0041353a 0246ffd0 00404198 0246ffd0 Main! Free + 0xda
08 0012ee1c 00404198 0246ffd0 0012 eecc 004e9b70 main! Operator delete + 0x9 (FPO: [349, 0]) (CONV: cdecl) [afxmem. cpp @]
09 0012ee38 00402a71 02477fe0 00000011 004e9ce0 main! Basic_string <char, char_traits_char, allocator <char >:: append_helper + 0x68 (FPO: [EBP 0x0012eecc] [2, 1, 4]) (CONV: thiscall)
...
NTDLL! 77f97710 ()
NTDLL! 77fb5721 ()
NTDLL! 77fa760a ()
NTDLL! Fc77ba9e ()
MSVCRT! 78001d92 ()
Operator delete (void * 0x00c266f8) line 6 + 10 bytes
Std: basic_string <char, std: char_traits <char>, std: allocator <char >:: _ Tidy (std: basic_string <char, std :: char_traits <char>, std: allocator <char> * const 0x0000000f {???}, Unsigned char 1) line 591 + 6 bytes
...
00 0184fb9c 60f3abc3 main! _ Sbh_free_block + 0x173
01 0184fbb4 60f2aa93 main! Free + 0x28
02 0184 fbbc 60f2423c main! Operator delete + 0x9
03 0184fce8 60f244b0 main! Function (std: basic_string <char, std: char_traits <char>, std: allocator <char> var = std: basic_string <char, std :: char_traits <char>, std: allocator <char>) + 0x79c
...
...
5ed 0198de20 77fac5f4 0198dec0 0198e3f8 0198 dedc ntdll! ExecuteHandler + 0x26
5ee 0198dea8 77f91a96 0198dec0 0198 dedc 0198dec0 ntdll! RtlDispatchException + 0x76
5ef 0198df14 77b22546 2cb01468 47ac0008 00000008 ntdll! KiUserExceptionDispatcher + 0xe
5f0 0198e340 1001b22c 00ed0000 00000000 00000080 ole32! SyncStubInvoke + 0x61
5f1 0198e37c 1001b123 00000080 1001a4ef 00000080 main! _ Heap_alloc + 0xed
5f2 0198e384 1001a4ef 00000080 00000001 100022f1 main! _ Nh_malloc + 0x10 (FPO: [2, 0, 0])
5f3 0198e390 100022f1 00000080 0000007c 0198f430 main! Operator new + 0xb (FPO: [1, 0])
5f4 0198e3b0 10002207 0000003c 0000007d 0198f42c main! Std: basic_stringbuf <unsigned short, std: char_traits <unsigned short>, std: allocator <unsigned short >:: overflow + 0x83 (CONV: thiscall) [C:/Program Files/Microsoft Visual Studio/VC98/INCLUDE/sstream @ 60]
5f5 0198e3cc 10003194 00000000 0000006b 0198f6e0 main! Std: basic_streambuf <unsigned short, std: char_traits <unsigned short> >:: xsputn + 0x6a (CONV: thiscall) [C: /Program Files/Microsoft Visual Studio/VC98/INCLUDE/streambuf @ 166]
5f6 0198e404 10005621 0198f42c 010113b2 1003573c main! Std: operator <+ 0xb0 (CONV: cdecl) [C:/Program Files/Microsoft Visual Studio/VC98/INCLUDE/ostream @ 305]
...

Cause
The standard template library (STL) is an insecure multi-threaded application in Microsoft Visual C ++. In particular, the implementation of std: string class depends on the basic_string <button> template class. Basic_string <button> template class reference count hides the copy of the character buffer. Store the count in an 8-bit unsigned char basic_string <button> template class. After implementation, the following common problems occur: • No basic_string <button> the template class does not protect the counting mechanism and requires related threads to run on a multi-processor computer at the same time. This problem can be avoided because only one thread runs at a time, and the multi-thread code running on a single processor computer of other threads can be interrupted before memory reading or integer writing is completed.
• Writing a std: string. The class in a thread may be damaged by a std: string class, such as a value assignment. Create a read in other threads. Supposed copies share the same hidden character buffer.
• String corruption may occur when pointers or references to a std: string class are shared among threads. Generally, it is responsible for avoiding this situation for programmers.

Solution
The application must be rebuilt after the thread STL is executed. The preferred method to obtain the thread STL is to upgrade STL to the new version based on the current VisualC ++ standard. The current VisualC ++ standard is based on STL, but it is not the same as STL. Microsoft VisualC ++ 6.0 cannot be released as a new product. However, upgrading to the new version may follow the STL function, and the application uses the common. To obtain the new version of the thread STL, use one of the following methods:
Method 1: use Microsoft Visual C ++. NET (7.0 and later)
Open each VisualC ++ project in the application, allow the project to be automatically converted to the new project format, and then recreate it. In this version, the std: string class implementation is a thread-safe description problem. If you use the DLL Runtime Library Function in any project, you must distribute the new VisualC ++ Runtime library components (such as Msvci7x. dll Msvcp7x. dll, and Msvcr7x. dll.

Note that you do not need to distribute data to client computers to use the Microsoft Visual C ++. NET Microsoft. NET Framework.
Method 2: Use Microsoft Visual C ++ 6.0 to remove STL from a third party
Detailed integration is supported by products and individual vendors. For subsequent STL versions, one source is Dinkumware, Ltd., where Microsoft License Visual C ++ 6.0 STL. It is occupied and integrated with the existing build process. For more information, and known defects and workarounds, visit the following Dinkumware Web site:
Www.dinkumware.com (http://www.dinkumware.com)
Microsoft provides third-party contact information to help you find technical support. This contact information may be changed without further notice. Microsoft does not guarantee the accuracy of this third-party contact information. Third-party products. This article discusses that the program is made independently of Microsoft. Microsoft makes any implied or otherwise in the form of no warranties regarding performance or reliability for these products.

Alternative Method
Solve the Std: String class problem in Microsoft Visual C ++ 6.0 STL
If you do not upgrade to the new version of STL, you can try to correct the std: string class thread security standard Microsoft VisualC ++ 6.0 installation. Although there are several Microsoft Visual C ++ 6.0 STL, the most common and problems in multi-threading classes are std: string classes. The following steps and work und are the stopgap measures to ensure that the application is normal and provide time to study other alternatives. Consider using these commands to create a new code path and possibly the entire application behavior. Thoroughly test the extensive deployment of application reconstruction programs prior to the extensive deployment of software policies prior to the company or individual software policies.

Disable string reference count
This section describes how to disable the reference counting mechanism. To disable reference counting, you must modify the header file <xstring> and set the _ FROZEN enumerated constant to 0. In addition, the <xstring> header file is installed by default in the following locations:
C:/ProgramFiles/Microsoft files/Microsoft Visual Studio/VC98/Include
Change the _ FROZEN enumeration constant to 0 in the header file on the row 62 page so that it is similar to the following: enum _ Mref {_ FROZEN = 0 }; // set to zero to disable sharing; original value 255
If you follow this advice and recreate all software using these header files, the std: string class code will be multithreading. There are some warnings about this statement. Therefore, read the following work und carefully. Disabling reference counting solves this problem by setting the _ FROZEN enumerated constant to 0 in the <xstring> header file.

Method 1: use static CRT Link
In all projects, use the STD: string class to link to the Microsoft Runtime Library (CRT) of the static version to modify the project settings. This method cannot be used if you enable the MFC settings in shared DLL in the project. For each project, follow these steps: 1. Open the project.
2. Click settings on the project menu.
3. In the configuration list, click Publish.
4. On the C/C ++ tab in the "category" list, code is generated in sequence.
5. In the Runtime Library list, click multi-thread MT )/(
6. In the configuration list, click debug.
7. In the Runtime Library list, click multi-thread debugging (MTD )/
8. If there are other configurations, set the appropriate Runtime Library in the configuration list for these options.
9. Click OK and recreate the project.
This work und ensures that the entire multi-thread Runtime Library is statically linked, including MFC, and all code uses the modified version of the <xstring> file. One possible problem is that the final code size will be greater than a dynamic link version, maybe enormously.

Method 2: Use Dynamic CRT Link
If the project code must be linked to the Runtime Library (CRT) as the DLL, other methods must be taken. The dynamic CRT link is the default setting for the DLL project. Depending on other components (such as MFC or third-party libraries used with applications, authorization usually needs to be dynamically linked to CRT. If you only rely on MFC, you can use the MFC option in the static library and apply method 1. By default, in Visual C ++ 6.0, when a project is created in Microsoft, the project uses CRT from the DLL.

The dynamic CRT link project sets the link application to preset Microsoft crt dll in some std: string methods, called Msvcp60.dll. Change to the _ FROZEN constant. Your local copy is <xstring> because the header file is modified by using <xstring>, Microsoft built-in DLL does not comply with function calls beyond this library. These include _ Tidy (), and assign () functions are provided for Msvcp60.dll files of the <char and <short> instantiations basic_string classes. The basic_string class is based on the std: string class.

To replace the Msvcp60.dll file, follow these steps to use the std: string class static implementation in the implementation module provided by Microsoft:
1. <xstring> file. The following code is found at the end of the file. In addition, you can add the code to # if 0/# endif block to comment.
# Ifdef _ DLL
# Pragma warning (disable: 4231)/* the extern before template is a non-standard extension */
Extern template class _ cribd basic_string <char, char_traits <char>, allocator <char>;
Extern template class _ cribd basic_string <wchar_t, char_traits <wchar_t>, allocator <wchar_t>;
# Pragma warning (default: 4231)/* restore previous warning */
# Endif // _ DLL

2. <string> the header file defines other string operators, which are included in the CRT through the msvcp60.dll file. We found a series... The "extern template _ cribd" <string> file, just as defined in the # ifdef _ DLL clause <xstring> file. Similarly, comment out all the following definitions:
# Ifdef _ DLL
# Pragma warning (Disable: 4231)/* the extern before template is a non-standard extension */

Extern template class _ cribd
Basic_string <char, char_traits <char>, Allocator <char> _ cdecl operator + (
Const basic_string <char, char_traits <char>, Allocator <char> &,
Const basic_string <char, char_traits <char>, Allocator <char >> &);
Extern template class _ cribd
Basic_string <char, char_traits <char>, Allocator <char> _ cdecl operator + (
...
Extern template class _ cribd
Basic_ostream <wchar_t, char_traits <wchar_t> & _ cdecl operator <(
Basic_ostream <wchar_t, char_traits <wchar_t> &,
Const basic_string <wchar_t, char_traits <wchar_t>, Allocator <wchar_t> &);

# Pragma warning (default: 4231)/* restore previous warning */
# Endif // _ DLL

3. Save these files and recreate all applications using STL projects. If the project declares the _ declspec (dllexport) Class and the class belongs to the STD: string type, the c1_1 warning is displayed. These warnings can be ignored when the STD: string class is generated because of all code and static links. To explicitly disable these warnings, use the following annotations: # pragma warning (Disable: 4251)

This method balances the use of the STD: string class outside of the MFC and CRT functions from the DLL. No small code size is added in each module using the STD: string class.

Method 3: use smart hackers to avoid link problems
It is created as an unsigned char type and used instead of an existing STD: string type. The type may need to be the source file of the application. Use the STD: String Class header file to include the form. Type may be similar to the following: typedef STD: basic_string <unsigned char> mystring;
# Define string mystring
Any use of such strings must be converted or processed as unsigned characters. The possible code size and simplified implementation increase with fewer link side effects.

Method 4: Use custom STD: String DLL
The benefit of small code size is that you can use the STD: string class placed in a single DLL to achieve this option. Create a DLL project and export the STD: string class. Link to the DLL instead of the standard msvcp60.dll file. Together with the application, you must distribute this new DLL. This is an advanced option.

More information
The following example of C ++ Code demonstrates that synchronization of a scheme may fail :...
STD: string;
A = "init ";
_ Beginthread (thread1, 0, (void *) & );
_ Beginthread (thread2, 0, (void *) & );
A = "";
...

Void thread1 (void * Arg)
{
STD: String a1 = * (STD: string *) ARG;
...
A1 = "newval ";
}

Void Thread2 (void * arg)
{
Std: string A2 = * (std: string *) arg;
...
Std: string B = A2;
A2 = "newval2 ";
}
In this example, Thread1 creates a copy input parameter and causes the shared character buffer to count with reference on 1. It is used. When Thread2 creates a copy, it is its input parameter, and the reference count is 2. At the same time, the main thread assigns A new value to A, creates A new character buffer, and removes the original shared buffer from the reference count on 1.

Thread1 create A new character buffer for new assignment to A 1, its previous shared character buffer, and then from 1 to 0, the count is reduced to identify the positive reference count. At the same time, Thread2 is also in the process of assignment to B. B shares the character buffer of A2, and raises the reference count on the character buffer of A2, trying to increment it to 2 just before Thread1 writes a 0 to the reference count. the reference count is modern for 1 0. If the access reference counter has been synchronized, the reference count is 0.

When Thread2 assigns a new value to A2, Thread2 will see that the reference count is 0, discard the original shared character buffer, and still reference B. Memory, reserved character buffer can be used in other applications immediately. However, B std: string still places the pointer in the character buffer. • B tries to release the character buffer zone.
• B tries to read the content of the character buffer that has been overwritten with real-time data by other code.
• Did not try to extend or modify the string.

Reference
For more information about the VisualC ++ language and compiler, see how to use the VC ++ thread with STL? Topics:
Http://www.mvps.org/vcfaq (http://www.mvps.org/vcfaq)

-------------

I used 2nd methods of alternative solutions. I disabled the string reference count and used the CRT dynamic link library, modify the # ifdef _ dll/# endif code block of the <string> and <xstring> header files.

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.