Select the product you need help with
STL std::string class causes crashes and memory corruption on multi-processor machinesArticle ID: 813810 - View products that this article applies to. On This PageSYMPTOMSWhen you build applications in Microsoft Visual C++ 6.0 that use the supplied Standard Template Library
(STL), memory corruption may occur, or your computer may stop responding. These symptoms occur more frequently on multi-processor computers.
Previously, the same code may have worked without such issues on a
single-processor computer. When you examine the faulting thread in a debugger, you typically see the failure in a memory management function. Frequently you see the basic_string<char...> class methods in the stack trace. Because memory
corruption is also a symptom, failures may appear in areas that are unrelated to string
processing. The following are examples of stack traces where this problem was the cause of a crash: CAUSEThe Standard Template Library (STL) that is included with Microsoft
Visual C++ 6.0 is not safe for multi-threaded applications. In particular, the
implementations of the std::string class depend on the basic_string<...> template class. The basic_string<...> template class reference
counts copies of a hidden character buffer. The basic_string<...> template class stores the count in an 8-bit
unsigned char. The following general issues occur after this implementation:
RESOLUTIONYou must rebuild the application after you make the STL
thread-safe. The preferred method to obtain a thread-safe STL is to upgrade
the STL to a newer version that is based on the current Visual C++ standard. However, the STL that is based on
the current Visual C++ standard is not identical to the STL that was available at the time
that Microsoft Visual C++ 6.0 was released as a new product. However, upgrading to a new
version may be trivial depending on the STL functions that your application uses. To obtain new versions of the thread-safe STL, use one of the following methods: Method 1: Use Microsoft Visual C++ .NET (versions 7.0 and later)Open each Visual C++ project in your application, allow the project to automatically convert to the new project format, and then rebuild it. The std::string class implementation in this version is thread-safe for the described problem. If you use the DLL run-time library feature in your any one of the projects in your application, you must distribute the new Visual C++ run-time components (such as Msvci7x.dll, Msvcp7x.dll, and Msvcr7x.dll) with your rebuilt application.Note You do not have to distribute the Microsoft .NET Framework to client computers to use Microsoft Visual C++ .NET. Method 2: Use Microsoft Visual C++ 6.0 with a replacement STL from a third partyThe details of integration vary by product, and the individual vendors provide support. One source for a successor STL version is Dinkumware, Ltd., the company where Microsoft licenses the Visual C++ 6.0 STL. It is claimed that it can integrate with existing build processes. For more information, and for a list of known bugs and workarounds, visit the following Dinkumware Web site:www.dinkumware.com Microsoft provides third-party
contact information to help you find technical support. This contact
information may change without notice. Microsoft does not guarantee the
accuracy of this third-party contact information.
The third-party products that this article discusses are
manufactured by companies that are independent of Microsoft. Microsoft makes no
warranty, implied or otherwise, regarding the performance or reliability of
these products.
(http://www.dinkumware.com)
WORKAROUNDWork around the std::string class issue in Microsoft Visual C++ 6.0 STLIf you do not upgrade to a new version of the STL, you can try to correct the std::string class thread-safety issue in the standard Microsoft Visual C++ 6.0 installation. Although there are multi-threading issues with several of the classes in the Microsoft Visual C++ 6.0 STL, by far the most common and problematic class is the std::string class. The following steps and workarounds are stopgap measures to make sure that an application is working correctly, and the measures provide time to investigate other alternatives. Consider that these instructions will create new code paths and behavior perhaps throughout your whole application. Thoroughly test the rebuilt application in accordance with a company's or an individual's software policies before widespread deployment.Disable string reference countingEach of the workarounds that is documented in this section require that you first disable the reference-count mechanism. To disable reference counting, you must modify the <xstring> header file and set the _FROZEN enumeration constant to 0. In default installations, the <xstring> header file is in the following location:C:\Program files\Microsoft Visual Studio\VC98\Include Change the _FROZEN
enumeration constant to 0 in the <xstring> header file at line 62 so that it looks
similar to the following: Method 1: Use static CRT linkage onlyModify the project settings in all your projects that use the std::string class to link to the static version of the Microsoft run-time library (CRT). You cannot use this approach if your project also has the Use MFC in a Shared DLL setting enabled. For each project, follow these steps:
Method 2: Use dynamic CRT linkageIf your project code must link to the runtime library (CRT) as a DLL, you must take a different approach. Dynamic CRT linkage is the default setting for DLL projects. Dependencies on other components such as MFC or third-party libraries that are licensed for use with your application, typically require dynamic linkage to the CRT. If your only dependency is MFC, you can use the Use MFC in a Static Library option, and apply Method 1. By default, when you create a new project in Microsoft Visual C++ 6.0, the project uses the CRT from a DLL.The dynamic CRT linkage project setting links your application to implementations for some std::string class methods in the pre-built Microsoft CRT DLL that is named Msvcp60.dll. Because Microsoft built that DLL by using the unmodified <xstring> header file, the change to the _FROZEN constant that you made to the local copy of <xstring> is not honored for functions that are called out of that library. These include functions such as _Tidy(), and assign() that are supplied in the Msvcp60.dll file for the <char> and <short> instantiations of the basic_string class. The basic_string class is the base for the std::string class. To use static implementations of the std::string class in your modules instead of the Microsoft-supplied implementations in the Msvcp60.dll file, follow these steps:
Method 3: Using a clever hack to avoid linkage issuesCreate a typedef for unsigned char, and use that instead of the existing std::string class typedef. The typedef may take a form that is included in a header file in the source files of the application that use the std::string class. The typedef may appear similar to the following:Method 4: Using a custom std::string DLLThis option gains you the benefit of smallest code size by putting the std::string class implementations in a single DLL. Create a DLL project that exports the std::string class. Link to that DLL instead of to the standard Msvcp60.dll file. You must redistribute this new DLL together with your application. This is an advanced option.MORE INFORMATIONThe following C++ code examples demonstrate one scenario
that may occur when there is a lack of synchronization: Thread1 starts to create a new character buffer for the new assignment to A1, recognizes a positive reference count on its previous shared character buffer, and then decrements that count by 1 to 0. 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 now 0 instead of 1. The reference count would have been 0 if access to the reference counter had been synchronized. When Thread2 assigns a new value to A2, Thread2 sees the reference count of 0 and discards the original shared character buffer that B still references. The memory that held the character buffer is now available for other uses in the application. However, std::string B still holds a pointer to the character buffer. The following scenarios cause corruption and crashes:
REFERENCESFor more information about Visual C++ language and
compiler issues, see the Is the STL included with VC++ thread-safe? topic at the following Microsoft Most Valuable Professional (MVP) Web site: http://www.mvps.org/vcfaq
(http://www.mvps.org/vcfaq)
PropertiesArticle ID: 813810 - Last Review: June 1, 2004 - Revision: 1.0
|



Back to the top








