Breaking Changes in Visual C++ 2005
There are a number of changes that you can expect to see in Microsoft Visual C++ 2005. In this article, I present a number of changes that can already be found in Visual C++ 2005 that you may encounter when upgrading your own programs. This information is based on a presentation and feedback by Brandon Bray (Visual C++ Program Manager), Alvin Chardon, and Sri Vasudevan.
There will be a number of changes in Visual C++ 2005 that will break past programs. These changes have not been made casually—generally there is a strong reason for the change. As developers using Visual C++, you should be aware of these changes before you upgrade.
Allowing Change in Visual C++
The Visual C++ team has an entire process for considering changes in the product. It is considered very serious when a change is being made to Visual C++ that could break prior code. Even so, there are a number of reasons for breaking code in a new edition:
One of the key features of Visual C++ 2005 is that it is even more conformant with the C++ standards. This allows for more portable code across platforms and into other tools. Things such as lifetime of variables declared inside a for scope (for-scoping) and variable types will now fit the C++ standards. Conformance to the standards will also be the default settings in Visual C++ 2005. To gain this conformance, some things that were allowed in the past may no longer work.
Security has been a very hot topic over the past few years and will continue to be critical going forward. C++ allows you the power to do nearly anything. To help alleviate the number of security issues and to make code less error prone, Visual C++ 2005 has a number of changes. It introduced a secure CRT and deprecated the unsecure APIs. It also introduced the security checks that are on by default now.
Serviceability has also been added to the product. This allows for easier updateability of the binary files in VC++. It will now be easier for vulnerabilities to be patched and fixed.
Maintenance can also be a cause for making breaking changes. For example, low-value features may be removed from the product to eliminate the need to continue to maintain them. As an example, single-threaded CRT was removed from Visual Studio 2005 because it really wasn't needed. There are better alternatives and the time previously spent maintaining this can now be focused on more important issues.
Finally, a breaking change may be added in order to increase the reliability of the VC++ compiler. Microsoft wants to insure there is a well-defined and consistent behavior within Visual C++.
Some changes are avoided. Most changes to Visual C++ are at the source code level. If these changes impact backward binary compatibility, the change may not happen. Source compatibility will be broken before binary compatibility will be. A change will also be avoided if it could seriously cause people to avoid adopting or upgrading to 2005. This can be changes because of breaking code or because it adds cost. Finally, a coding change must have enough value to justify the cost of making the change. If the cost isn't justified, there is obviously no point in implementing it.
Ten Breaking Changes in the Visual C++ Library
There are a number of changes in the Visual C++ 2005 Libraries that could break your existing application code. Before upgrading to Visual C++ 2005, you should verify that you don't have any of these issues in your application code.
In the C Runtime Libraries, code has been added to validate parameters. For example, if you pass a destination buffer whose size is smaller than necessary to strcpy, you can cause a security risk. Parameter validation code will invoke an invalid parameter routine. In release, this will call Dr. Watson. In debug, it will assert. As long as you are passing valid parameters, this will not be an issue.
If you are passing invalid parameters, this will break your code.
Warnings for Insecure APIs
A set of functions within the CRT has been deprecated. New secure versions have been provided. Most of the deprecated functions can cause a buffer overrun or other security issue, if improperly used. These are functions such as strcpy, strcat, and so forth. The new, secure versions have been given a suffix of _s to make them easily identifiable. For example, functions include strycpys ,wcscpy_s, mbscpy_s, calloc_s, and strcat_s.
If you want to continue to use the old, insecure versions of these functions, you can use a #define value of _CRT_SECURE_NO_DEPRECATE. It is recommended, however, that you update your code to use the secure versions.
Iterators Out of Range
SCL checked iterators and debug iterators have been updated for security reasons. If you go out of range with a checked iterator, an "invalid parameter" routine will be called.
Again, you can avoid the invalid parameter and have an out-of-range exception thrown instead. This can be done by using the #define value of _SECURE_SCL_THROWS. By setting this define value to 1, an exception will be thrown instead of calling the invalid parameter handler.
You can turn this iterator checking off by setting the #defined value of _SECURE_SCL to zero. By default, this is turned on.
The type, time_t, is used to represent time in seconds from 1970. Up until 7.1, this was defined as a long. It is now of type 64-bit, so you can do times to the year 3000.
Linking to CRT
Managed applications cannot statically link to CRTs. Whereas you could build a CLR application in 7.0 and 7.1 by linking statically to the CRT, you cannot do that in 2005.
Single-Threaded CRT Support
Single-threaded CRT support has been removed. You had an option to link to the multi-threaded or single-threaded CRT. Going forward, it is believed that most people will want to work with the thread-safe multi-threaded routines.
_nolock suffix routines can be used to optimize your code. In exchange for being optimized, these functions are not thread safe.
There are two types of exception handling that you could use: /EHa (asynchronous) and /EHs (synchronous C++ exceptions). If you used the /EHs switch, on a catch(...) block you may or may not have caught structured exceptions; the behavior was undefined and thus unreliable. You are now guaranteed that structured exceptions will not be caught when /EHs is used. If you want to catch asynchronous exceptions, you should compile using the /EHa switch.
Order of Initialization
Behavior was not defined if you had both managed and native globals. If you had a managed and a native object that interacted, there was no guarantee as to which would be initialized first. Now, you are guaranteed that all native globals will be initialized first, followed by managed globals.
The %n format specifier in the printf set of functions will allow for printing the number of characters printed so far. This was a security risk and has thus been disabled. It can be enabled by using set_printf_count_output. Passing set_printf_count_output a 0 (zero) disables it. Passing any other value enables it.
The swprintf function
The swprintf function signature did not conform to the C++ standard, so it was changed to fit the standard. In C++, an overload was added with the appropriate arguments. The prior version of the method has been deprecated. In C, overloading is not allowed, so an error will be returned if you use the old format.