Welcome to MSDN Blogs Sign in | Join | Help

X64/Itanium platforms missing when Win7 SDK RC installed sidebyside with VS2008 RTM

If Win7 SDK (RC) is installed SidebySide with Visual Studio 2008 RTM before Visual Studio 2008 SP1 is installed, x64 and Itanium platform will not be available from the New Platform drop-down list. Build targeting x64 and Itanium will also fail. To work around the issue, please refer to this post.  Note that the issue has been fixed in Win7 SDK RTM.

Thank you,

Visual C++ Team

Posted by vcblog | 1 Comments

STL Performance

Hello, I am Mohammad Usman, a Software Design Engineer in Test on the Visual C++ Libraries team. I recently joined the team. In VS 2008 SP1, we invested heavily in our Standard Template Library (STL) implementation by adding TR1 extensions such as shared_ptr, including performance optimizations for things like vectors of shared_ptrs.  In this post, I will be talking about how we take this investment further by improving our STL performance in VS2010. We have done some re-writing of our libraries to make them more conformant to the C++0x standard, more flexible and extendible, and to improve performance in a few areas. For the first two items we already have a few blog posts and a Channel 9 video, this post will mainly cover the performance part.

Since we have re-written quite a bit of STL code in order to improve flexibility and increase conformance, it was important to make sure that this does not negatively affect the performance. We have taken special care of that. Most of our performance tests are to ensure this. And our tests are showing good results. In fact there are some areas where VS2010 is faster than VS2008. Some of those areas where we improved performance significantly are:

-          Overall deque performance

o   The improvement is evident when used with algorithms such as std::reverse(), std::remove(), std::sort() and std::unique().

-          std::unique() 

o   An optimization change in the loops of the function has given a significant performance boost when used with different containers such as list, deque and vector.

-          Vector reallocations

o   Vector is one of the most commonly used containers because of its attributes such as contiguous memory, random access, fast traversals, and its ability to grow dynamically etc. But it does have some limitations. To maintain contiguous memory, it has to allocate memory in a chunk and when that chunk is full, it has to go through something called “reallocation”. This is a potentially costly process causing the vector to copy all the contents to a new location. Now the good news is that we have made very significant improvements there in VS2010 with the help of rvalue references.  This will come into action when you use vectors with STL objects in VS2010 and you can also take advantage of this when using vectors of your own custom objects by writing simple move constructors, move assignment operators for your class. A significant performance gain will be evident here when used with large objects containing strings. This is explained in more detail below.

Vector Reallocation (UDTs - User Defined Types)

Introduction of rvalue references in STL is one of my favorite enhancements for VS2010. “Rvalue references” is quite a complicated topic. Stephan (our STL developer) recently wrote a very good comprehensive blog post explaining rvalue references, which can be found here. For the sake of this post, I will touch only the parts which impact the performance of STL.

By using rvalue references, we are able to move the contents of objects rather than copying and destroying the original where we don’t have to. We actually “steal” the resources by copying the pointers rather than the whole object when the object we are dealing with is an rvalue. This is most helpful when move constructors and move assignment operators can be used. You can use the move machinery to write your move constructors and move assignment operators. The following simple test shows that we can get an order of magnitude performance boost when we take advantage of rvalue references in large UDTs.

 

#include <iostream>

#include <ostream>

#include <ios>

#include <stddef.h>

#include <string>

#include <vector>

#include <windows.h>

#include <utility>

 

 

//***************************** START: <Helper Code> ***********************************

 

long long counter() {

    LARGE_INTEGER li;

    QueryPerformanceCounter(&li);

    return li.QuadPart;

}

 

long long frequency() {

    LARGE_INTEGER li;

    QueryPerformanceFrequency(&li);

    return li.QuadPart;

}

 

// to confine the test to run on a single processor in order to get consistent results for all tests.

void perf_startup() {

    SetThreadAffinityMask(GetCurrentThread(), 1);

    SetThreadIdealProcessor(GetCurrentThread(), 0);

    Sleep(1);

}

 

 

//***************************** END: <Helper Code> ***********************************

 

// User Defined Type

class myUserObject

{

public:

       std::string name;

       std::string address;

       std::string telephone;

       std::string name2;

       std::string address2;

       std::string telephone2;

 

       // default constructor

       myUserObject()

       {}

      

       // Copy Constructor

       myUserObject(const myUserObject& myObj)

       {

              name = myObj.name;

              telephone = myObj.telephone;

              address = myObj.address;

              name2 = myObj.name2;

              telephone2 = myObj.telephone2;

              address2 = myObj.address2;

       }

 

// copy assignment operator

       myUserObject& operator=(const myUserObject& myObj)

       {

              name = myObj.name;

              telephone = myObj.telephone;

              address = myObj.address;

              name2 = myObj.name2;

              telephone2 = myObj.telephone2;

              address2 = myObj.address2;

             

              return *this;

       }

      

       // As VS2008 does not have rvalue reference support

       #if _MSC_VER >= 1600

      

       // move constructor

// This is where are getting our performance gain.

// The move() machinery is made available in <utility>

       myUserObject(myUserObject&& myObj)

       {

              name = std::move(myObj.name);

              telephone = std::move(myObj.telephone);

              address = std::move(myObj.address);

              name2 = std::move(myObj.name2);

              telephone2 = std::move(myObj.telephone2);

              address2 = std::move(myObj.address2);          

       }

      

       // move assignment operator

       myUserObject& operator=(myUserObject&& myObj)

       {

              name = std::move(myObj.name);

              telephone = std::move(myObj.telephone);

              address = std::move(myObj.address);

              name2 = std::move(myObj.name2);

              telephone2 = std::move(myObj.telephone2);

              address2 = std::move(myObj.address2);

             

              return *this;

       }

 

       #endif

      

};

      

 

int main()

{

       perf_startup();

 

       int total_copy_move_count = 0;

int total_vector_resizes = 0;

double total_pushback_time = 0.0;

 

       std::vector<myUserObject> vec;

       myUserObject obj;

       obj.name = "Stephan T. Lavavej Stephan T. Lavavej Stephan T. Lavavej";

obj.telephone = "314159265 314159265 314159265 314159265 314159265";

       obj.address = "127.0.0.0 127.0.0.0 127.0.0.0 127.0.0.0 127.0.0.0 127.0.0.0";

obj.name2 = "Mohammad Usman. Mohammad Usman. Mohammad Usman. ";

       obj.telephone2 = "1234567890 1234567890 1234567890 1234567890 1234567890";

       obj.address2 = "Republik Of mancunia. Republik Of mancunia Republik Of mancunia";

 

       const long long start = counter();

       for (int i = 0; i<1050000; ++i)

       {            

      

              size_t capacity = vec.capacity();

              size_t size = vec.size();

             

              vec.push_back(obj);

 

              if (capacity == size) // indication that vector reallocation has occurred.

              {

                     ++total_vector_resizes;

                     total_copy_move_count += size;   

              }

       }

       const long long finish = counter();

       total_pushback_time = (finish-start)*1.0 / frequency();

 

       // print result

std::cout << std::endl;

       std::cout << std::fixed;

       std::cout << "Total Pushback time: \t" << total_pushback_time << " sec" << std::endl;

       std::cout << "Total number of vector reallocations: \t" << total_vector_resizes << std::endl;

       std::cout << "Total number of objects copied/moved: \t" << total_copy_move_count << std::endl;

}

 

 

VS2008:

c:\TEMP\STLPerf>cl /EHsc /nologo /W4 /O2 /GL /D_SECURE_SCL=0 rvalue.cpp

rvalue.cpp

Generating code

Finished generating code

 

c:\TEMP\STLPerf> rvalue.exe

 

Total Pushback time:    8.309241 sec

Total number of vector reallocations:   36

Total number of objects copied/moved:   3149622

 

VS2010:

c:\TEMP\STLPerf>cl /EHsc /nologo /W4 /O2 /GL /D_SECURE_SCL=0 rvalue.cpp

rvalue.cpp

Generating code

Finished generating code

 

c:\TEMP\STLPerf> rvalue.exe

 

Total Pushback time:    2.335225 sec
Total number of vector reallocations:   36
Total number of objects copied/moved:   3149622

As you can see that in this specific scenario we are getting more than 3 times performance boost. This gain is due to the fact that the move machinery is used during vector reallocations, which is cheaper as compared to the copy machinery (copy construction and copy assignment). And the bigger your object is and the larger your vector is, the more performance gain you will get. So those of you who use vectors on a big scale, this is something you will surely love.

Vector Reallocation (STL Types)

Now the interesting part is that similar to the sample code above, we have implemented move semantics (move constructors and move assignment operators) for our STL types in VS2010. It is worth mentioning here that for some types, in order to improve performance especially in situations where the copy was taking a lot of time such as vector reallocation, we used a trick called “swaptimization” before VS2010. (see pt.#16 in this blog post) Now with the arrival of rvalue references we don’t need that anymore and we have replaced those swaptimization tricks with the rvalue reference machinery and, guess what, we are now even faster. The following example shows one such scenario where we used swaptimization earlier.

#include <iostream>

#include <ostream>

#include <ios>

#include <stddef.h>

#include <string>

#include <vector>

#include <windows.h>

 

 

//***************************** START: <Helper Code> ***********************************

 

long long counter() {

    LARGE_INTEGER li;

    QueryPerformanceCounter(&li);

    return li.QuadPart;

}

 

long long frequency() {

    LARGE_INTEGER li;

    QueryPerformanceFrequency(&li);

    return li.QuadPart;

}

 

// to confine the test to run on a single processor in order to get consistent results for all tests.

void perf_startup() {

    SetThreadAffinityMask(GetCurrentThread(), 1);

    SetThreadIdealProcessor(GetCurrentThread(), 0);

    Sleep(1);

}

 

//***************************** END: <Helper Code> ***********************************

 

int main()

{

       perf_startup();

 

       long long total_copy_move_count = 0;

long long total_vector_resizes = 0;

double total_pushback_time = 0.0;

 

       std::vector<std::string> v_str;

 

       long long start = counter();

       for (int i = 0; i<12000000; ++i)

       {

              size_t size = v_str.size();

              size_t capacity = v_str.capacity();

              v_str.push_back("I think, therefore I am");

             

              if (size == capacity) // indication that vector reallocation has occurred.

              {

                     ++total_vector_resizes;

                     total_copy_move_count += size;          

              }     

       }     

       long long finish = counter();

       total_pushback_time = ((finish - start)*1.0 / frequency());

      

       std::cout << std::fixed;

       std::cout << std::endl;

       std::cout << "Total Pushback time: \t" << total_pushback_time << " sec" << std::endl;

       std::cout << "Total number of vector reallocations: \t" << total_vector_resizes << std::endl;

       std::cout << "Total number of objects copied/moved: \t" << total_copy_move_count << std::endl;

 

}

 

 

VS2008:

c:\TEMP\STLPerf>cl /EHsc /nologo /W4 /O2 /GL /D_SECURE_SCL=0 swaptimization.cpp

swaptimization.cpp

Generating code

Finished generating code

 

c:\TEMP\STLPerf> swaptimization.exe

 

Total Pushback time:    6.717094 sec

Total number of vector reallocations:   42

Total number of objects copied/moved:   35875989

 

VS2010:

c:\TEMP\STLPerf>cl /EHsc /nologo /W4 /O2 /GL /D_SECURE_SCL=0 swaptimization.cpp

swaptimization.cpp

Generating code

Finished generating code

 

c:\TEMP\STLPerf> swaptimization.exe

 

Total Pushback time:    3.780286 sec

Total number of vector reallocations:   42

Total number of objects copied/moved:   35875989

 

You can see that moving to rvalue references hasn’t impacted the performance. In fact, in this particular example, we are almost twice as fast as VS2008. The credit for this gain also goes to rvalue references, not specifically during vector reallocation, but during push_back() instead. As you can see that we are passing a literal string (an rvalue- see footnote) to the function. So the move machinery comes into play here again, giving us another performance boost.   

This is all what I have to share in my blog. If you have any questions about performance of STL or in general about STL, please feel free to write to me at: Mohammad.Usman at microsoft.com.

Thanks!

 

-Usman

 

* String literals are actually lvalues (C++03 5.1/2), whereas all other literals are rvalues.  However, since we’ve got a vector<string>, push_back() takes const string&.  This constructs a temporary std::string, which is an rvalue.  That’s where move semantics comes into play.

 

Posted by vcblog | 16 Comments

Channel 9 Video: Bogdan Mihalcea: The New VC++ Project/Build system - MSBuild for C++

Bogdan Mihalcea is a developer on the Visual C++ team. During the development of Visual Studio 2010 he has been feverously working on converting our build system to target MS Build as the build infrastructure for  Visual C++ 2010 Solutions/Projects. There are many reasons motivating this changeover. For awhile now having to deal with two different build systems, VC Build and MS Build, has been a little bothersome for many of our customers who had a mix of native and managed code. Secondly, a lack of parity would mean that  useful features appeared in one system which may not be mirrored in the other. Finally, we could not move two infrastructures forward as fast as we will be able to move one. So what does VS2010 have in store for your Visual C++ Solutions/Project and what amount of effort it may take you to get there – watch the video to find out. As always, we hope you enjoy the video and feel free to post any questions you like on the Channel 9 site.

 

Thanks

Damien

Posted by vcblog | 0 Comments

Channel 9 Video: David LeBlanc (and Ale Contenti): Inside SafeInt

David LeBlanc and Michael Howard literally wrote the book on “Writing Secure Code”. David has also developed the SafeInt  class, a template class that performs “checked” operations on integer types (with a name like SafeInt what else would you expect). In VS2010 we decided to ship the SafeInt class in the box, so users no  longer need to go and download it separately and “install” it themselves. Ale Contenti was the main  instigator behind this decision and now that VS2010 Beat 1 has shipped, Ale and David meet with Charles from Channel 9 to talk about the class and it uses. We hope you enjoy the video and feel free to post any questions/feedback on the Channel 9 site.

 

Thanks

Damien

Posted by vcblog | 0 Comments

Call Hierarchy

Hello everyone,

My name is Raman Sharma and I am a PM on the VC++ IDE team.  I want to talk about a new feature called Call Hierarchy in Visual Studio 10.  As the name suggests, it is used for navigating all functions called from within a particular function and all functions that make calls to a particular function.  Many of you would know of a feature called Call Browser which was present in VC6, VS2005 and VS2008, and provided similar functionality.  The Call Hierarchy feature is the revamped version of Call Browser, better organized and easier to use.

In VS2010, Call Hierarchy has been designed such that it can be a shared feature for all languages i.e. the UI is common and different languages (like C#, C++ etc.) can fill the UI with their own data to address the semantic differences between the languages.  For C#, this will be a new feature (See this post for more details).  For C++, it is just about transitioning from the old Call Browser to Call Hierarchy to take advantage of the new design. 

Let’s look at an example that will illustrate the differences between the old functionality and the new one.  Let’s say you want to see the “calls from” and “calls to” information for two functions at the same time: CImagingView::OnRButtonUp and CImagingView::OnContextMenu

In the previous releases, this would have effectively meant you having to open the following four call browser tool windows:

C++ Call Browser in VS2008

The above model clearly suffers from the following limitations:

-          The “Calls From” and “Calls To” are presented in separate tool windows. (windows 1&3 for Calls To and 2&4 for Calls From)

-          Each tool window can hold the call information for only one function at a time.

-          The manner in which results are presented is not very intuitive:

o   In the window 2 above, the names of the functions called from CImagingView::OnContextMenu are listed at the bottom of the tree, whereas the actual calls to those functions are listed under the folder named Calls from ‘OnContextMenu’.

o   There is no link between the above two making navigation harder.

Let me just add, those windows would not be so neatly stacked together as I make them appear in the above screenshot.

In VS2010 however, with the new Call Hierarchy feature, the same information is presented in one tool window in the following form:

C++ Call Hierarchy in VS2010

Notice the following salient features in the above window:

-          “Calls From” and “Calls To” trees for any function appear in the same place in one window.

-          There can be multiple root nodes, thus obviating the need to open a separate window for each function.

o   The user can also right click on any non-root node in the tree and add it as a new root node to achieve better clarity.

-          The results are much clearer to comprehend:

o   The tree in the left pane of the window will just show the names of the function (callers or callees) recursively.

o   When you click on a result in the left pane, the actual call site appears in the right pane. 

o   Upon double clicking the call-site in the right-pane, you are taken to that location in your source code in the Editor. 

-          The user can limit the search results to the current file, the current project or the entire solution for better filtering and performance.

-          The user can copy the results from the call-sites pane and paste them elsewhere to perform some analysis.

There was no way to do any of the above using the old Call Browser.

The Call Hierarchy window can be invoked from the Editor context menu by just right-clicking on the function for which you want to see the results:

Call Hierarchy Invocation

 

To build this feature, we have made use of the new C++ IDE infrastructure, the details of which were posted here recently.  To populate the “calls from” information for a function say func, we simply need to parse the contents of func and find out all the functions being called from within it.  “Calls To” performs a wider search.  A query is made to the SQL based database (explained here again) to find out all the locations where func is referenced, and then for all the results, their enclosing blocks of code are parsed to find out whether this reference actually is a function call to func.  We have tried to make sure that the results we provide to you are accurate and complete.  However, we don’t claim to provide debugger-like accuracy.  For example, you will not see implicit calls like destructors etc. being listed in the list of calls from a function (some day maybeJ).  However, we have done enough to ensure that all the information relevant while designing, writing and reading code is available.  

Overall, we believe that new intuitive user interface, greater flexibility, fewer navigation steps, and better accuracy make the new Call Hierarchy a very useful feature.  We are excited about it and hope you will like it.

Thank you.

Posted by vcblog | 35 Comments

VS Project Team Blog Is Up!

The VS Project team, part of Platform team, own the C# and VB project systems brought their expertise to the table along with the VC++ team to give you an extensible and much more powerful project system.  The team maintains a blog at http://blogs.msdn.com/vsproject/ where we will blog about project system topics in much more detail. Stay Tuned!!!

 

Thank you,

 

Visual C++ Team

Posted by vcblog | 2 Comments

Follow up On Feedback From Beta1 and DevLab About VC Project Conversion’s Performance

Hi,

 

My name is Bogdan Mihalcea and I’m a developer on the C++ Project & Build team. In the last 2 years I worked on a new C++ project system build on top MSBuild.

 

I’m writing this blog to share some excellent news related to improvements we made to the performance of project conversion since the Beta1 build. This was possible because of the feedback we got from you, and I want to thank you for doing so!

 

During our development milestones, we had tests reporting that we have a very slow conversion for specific types of projects. They were usually containing many files (1000+) and they had a significant percentage of them containing file level configurations. After we analyzed the root cause and the costs of fixing, we made the assumption that these projects with many file level configurations were not very common, so the impact of the performance in this scenario would be low. Another assumption we made was that the conversion it is a onetime thing so the impact even if big for those rare cases it is a onetime tax. Based on these assumptions we prioritized the fix lower and decided to invest our time in making the performance of main line scenarios better.

 

Our team has a customer plan which includes the early release of the product through Beta1 and having various face to face meetings with customers. One of these events is the Visual C++ DevLab, which last time we kept in May 09. During this event we noticed that 20% of the customers were experiencing a very slow conversion.

 

We investigated and we realized that all cases were caused by less than 5% of the projects in the solution, which took the majority of conversion time. One common detail about those few projects is that they were very heavy on file level configurations. From the discussions with the customers we realized that it is unfortunately easy to get in that state due to various reasons (evolutionary codebases, easy to cause human error due to bulk select, bugs in previous conversions, not a easy bulk way to revert the file level configurations to project level).

 

That pretty much invalidated our assumption that it is not common to get in a situation where a customer can have a project with 1000+ files and more than half have file level configurations. The first assumption was also invalidated from the discussions we had with the customers and from feedback we received from Beta1’s customers, which revealed that even if the projects that have this case are not very common the unfortunate thing is that it is common for customers with hundreds of projects have 1 or 2 of these and that will impact the whole experience of the conversion for a much bigger percentage of the customers, than what we estimated earlier.

 

Furthermore the second assumption was challenged as well as we learnt from your feedback that conversion might not be a onetime tax as most of the companies prefer to stay for months in a dual state with the development done in parallel on both products and it is common to maintain only the previous version files as a baseline for changes and to reconvert always when the new product is used. Considering the new feature we added in Dev10, native multitargeting, this seems to make this approach even more popular.

 

After we got all this feedback we acted on it. We analyzed the code paths and we found places where we could optimize for this type of scenarios and made the fix. Below is an extract from our measurements before and after the fix.

 

Project

Files/vcproj

Configurations

% files in vcproj with FileConfigurations

Previous Conversion Time

Current Conversion Time

Customer

~4000

4

50%

55 min

8 sec

MVP

~5000

8

80%

1h 40min

23 sec

PerfLab test

~200

2

less than 10%

2.8s

1.4s

Customer

~200

16

100%

50 min

10 sec

 

The common case projects (PerfLab test), with only few file level configurations, were impacted too as you can see from the above table. We used pristine lab machines dedicated to performance runs and the results are specific numbers to these machines.

 

We are constantly on lookout for feedback and we are adjusting our priorities based on it, and we will try to keep you guys up to date with the progress we make.

 

Regards,

Bogdan Mihalcea

C++ Project & Build

Posted by vcblog | 10 Comments

Channel 9 Video: Louis Lafreniere: Next Generation Buffer Overrun Protection - gs++

Thanks to a recent VC Blog post by Hongwei Qi, you already know that we have worked on our /GS switch for VS2010. You can already try it out with the VS2010 Beta 1 too. Recently Charles Torre from Channel 9 stopped by and spoke with one of our Channel 9 regular speakers Louis Lafreniere about this work. Native code developers care deeply about getting both performance and security correct in their applications – and /GS impacts both of these. Please enjoy the video and feel free to post any questions/feedback on the Channel 9 site – we are very keen to know how the changes affect your applications.

 

Thanks

Damien

Posted by vcblog | 0 Comments
Filed under:

C++ Gets Squiggles!

Hello, I’m Mitchell Slep, a developer on the Visual C++ compiler team.  I’m very excited to tell you about a new feature in Visual Studio 2010 - C++ IntelliSense can now display compiler-quality syntax and semantic errors as you browse and edit your code!  

We display a wavy underline or “squiggle” in your code at the location of the error.  Hovering over the squiggle will show you the error message.  We also show the error in the Error List window.  The squiggles are great for showing you errors in the code you are currently viewing or editing, whereas the Error List window can help you find problems elsewhere in the translation unit, all without doing a build.

Designing the feature

We had two scenarios in mind when designing this feature.  One is of course productivity – it’s very convenient to be able to fix errors as they happen instead of waiting to discover them after a build, which can save you a lot of time.  We also wanted to improve the experience when IntelliSense doesn’t work.  IntelliSense has always been a black box – it often worked well, but if it didn’t, you had no idea why.  Now IntelliSense has a powerful feedback mechanism that allows you take corrective action – either by fixing errors in your code or making sure your project is configured correctly.

One decision we had to make when designing this feature was how often to update the errors as you edit your code.  If we don’t do it often enough, the errors quickly become out of date and irrelevant.  But doing it too often can also lead to irrelevant results, like a squiggle under ‘vect’ while you’re in the middle of typing ‘vector’!  We also don’t want to hog your CPU with constant background parsing. 

We found that a good balance was to wait for 1 second of idle time after you edit or navigate to a new part of the code before beginning to update the errors.   In this case ‘idle’ means that you haven’t typed anything and you haven’t navigated to a different part of the code.

We also experimented with some different designs for what to do with existing errors during the short window of time between when you make an edit and when the newly updated errors are available.  For instance, one design we tried was to clear all squiggles on the screen immediately after an edit, and then redraw the new errors when they are available.  We also considered a variant of this where we only clear the squiggles on the lines below the location of your edit (since making an edit can generally only affect code appearing after it). These designs have the advantage that you never see a stale squiggle, but in usability studies we found that this produced an annoying flickering affect, and also some confusion as to whether a squiggle disappeared because it was fixed or because it was just temporarily being updated.  The design we went with was to leave existing squiggles in place after an edit, and then swap them with the new errors when they are available.  This works well since the updates are very fast.

Technical Challenges

One of the technical challenges with this feature was making it fast.  As many of you know, large C++ projects can often take several hours to build.  One of the ways we get around this is by having IntelliSense focus on a single translation unit at a time (a translation unit is a .cpp file plus all of its included headers).  However, even that didn’t give us the kind of responsiveness we wanted for a live-compilation feature like squiggles. 

To get even better performance, we’ve developed some innovate incremental parsing techniques that minimize the amount of code we need to parse.  This allows IntelliSense to parse your code much faster than the time it would take to do an actual build (or even the time it would take to compile a single .cpp file).  The ideas are simple, but are challenging to implement in a complex, context-sensitive language like C++. 

When you first open a file, we parse just enough code to build up a global symbol table, skipping over a lot of code (like function-bodies) that only introduces local symbols.  Once we’ve built up the symbol table, we lazily parse the code that we skipped “on-demand”.  For instance, we only parse the inside of a function body when you actually view it on the screen.  If you make changes inside a function body, we are able to reparse just that function body.  Of course, all of this only happens during idle time, as described above.  These parsing techniques allow us to show you fast, relevant errors even as you edit large, complex code bases.

External build systems

If your solution already builds with Visual Studio, you will immediately benefit from having accurate syntax and semantic errors reported by IntelliSense as you browse and edit your code.  But this feature is also good news for those of you with external build systems.  The IntelliSense errors in the Error List window can guide you towards setting up a solution with accurate IntelliSense.  For instance, if you load up a solution configured for an external build system, you might see something like this:

Now you know that you need to adjust your Include Path.  Making these tweaks to your solution will dramatically improve the quality of IntelliSense you get with an external build system.

It’s been a lot of fun working on this feature and especially dogfooding it – it’s great not to have to do builds all the time!  You can preview this feature in Beta 1 and I look forward to hearing your feedback in the comments.

 

Posted by vcblog | 17 Comments

Off to California

The Visual C++ team is hosting a summit with ISVs in the San Jose / Bay Area next week. We have two full days packed with sessions centered on native code. Attendees will learn how Visual C++ 2008 provides a powerful and flexible development environment for creating Microsoft Windows–based applications. In addition, now that we have released Visual Studio 2010 Beta 1, we’re going to dive in and talk about all the great things coming in the future for C++ developers. From Windows 7 and multi-core development to the architectural changes in the IDE, we hope there will be lots to discover and learn.

Here’s a sample of the talks we’ve got planned…

Developing for Windows 7

The Windows® 7 operating system empowers ISVs to deliver innovative solutions that provide compelling application experiences.   This session introduces Windows 7 and highlights key advances for developers including the new taskbar, jump lists, libraries, Federated Search and the Windows Ribbon.

 

Compiler Improvements in VS 2010

The C++ compiler in VS2010 supports a number of new features, on the front-end these include C++0x features such as the repurposing of the auto keyword and the additional of new keywords/functionality such as  decltype, lambda functions, rvalue references and static_assert. In addition, we've improved the compiler backend and linker to run faster and generate better machine code.  We more efficiently leverage instructions such as cmov, use XMM registers for faster memcpy and improved code generation for some key scenarios, such as SIMD intrinsics programming. There are also security enhancements to the /GS switch.

 

Concurrency for C++ Developers

Over the last 30 years, the software industry has relied on exponential growth in processor power in order to improve performance, increase functionality, and enhance user experiences. Unfortunately, this "free lunch" is over. Instead of increasing the clock speed of processors, the hardware industry is shifting to multi-core and manycore processors. However, most software today typically is written to utilize only a single core and will not take advantage of most that this new hardware has to offer. The key to high-performance applications of the future is parallelism. This session explores new building blocks in Visual C++ 10 for creating responsive C++ programs that take full advantage of this new hardware. As part of this, we examine new programming models for parallelism and concurrency, including the Parallel Pattern Library (PPL) and the new asynchronous agents APIs, as well as the new Concurrency Runtime (ConcRT), which enables efficient execution of parallel applications. In addition, this session examines new Visual Studio tools to assist in the debugging of parallel applications as well as new profiling support for tuning parallelized applications in order to maximize performance.

 

We’ll post some of the materials after the event so watch this post for updates!

Posted by vcblog | 5 Comments

Rebuilding Intellisense

Hi, my name is Boris Jabes. I've been working on the C++ team for over 4 years now (you may have come across my blog, which has gone stale...). Over the past couple of years, the bulk of my time has been spent on re-designing our IDE infrastructure so that we may provide rich functionality for massive code bases. Our goal is to enable developers of large applications that span many millions lines of code to work seamlessly in Visual C++. My colleagues Jim and Mark have already published a number of posts (here, here and here) about this project and with the release of Visual Studio 2010 Beta 1 this week; we're ready to say a lot more. Over the next few weeks, we will highlight some of the coolest features and also delve into some of our design and engineering efforts.

In this post, I want to provide some additional details on how we built some of the core pieces of the C++ language service, which powers features like Intellisense and symbol browsing. I will recap some of the information in the posts I linked to above but I highly recommend reading the posts as they provide a ton of useful detail.

The Problem

Without going into too much detail, the issue we set about to solve in this release was that of providing rich Intellisense and all of the associated features (e.g. Class View) without sacrificing responsiveness at very high scale. Our previous architecture involved two (in)famous components: FEACP and the NCB. While these were a great way to handle our needs 10+ years ago, we weren’t able to scale these up while also improving the quality of results. Multiple forces were pulling us in directions that neither of these components could handle.

1.       Language Improvements. The C++ language grew in complexity and this meant constant changes in many places to make sure each piece was able to grok new concepts (e.g. adding support for templates was a daunting task).

2.       Accuracy & Correctness. We need to improve accuracy in the face of this complexity (e.g. VS2005/2008 often gets confused by what we call the “multi-mod” problem in which a header is included differently by different files in a solution).

3.       Richer Functionality. There has been a ton of innovation in the world of IDEs and it’s essential that we unlock the potential of the IDE for C++ developers.

4.       Scale. The size of ISV source bases has grown to exceed 10+ million lines of code. Arguably the most common (and vocal!) piece of feedback we received about VS2005 was the endless and constant reparsing of the NCB file (this reparsing happened whenever a header was edited or when a configuration changed).

Thus, the first step for us in this project was to come up with a design that would help us achieve these goals.

A New Architecture

Our first design decision involved both accuracy and scalability. We needed to decouple the Intellisense operations that require precise compilation information (e.g. getting parameter help for a function in the open cpp file) from the features that require large-scale indexes (e.g. jumping to a random symbol or listing all classes in a project). The architecture of VS2005 melds these two in the NCB and in the process lost precision and caused constant reparsing, which simply killed any hope of scaling. We thus wanted to transition to a picture like this (simplified):

At this point, we needed to fill in the blanks and decide how these components should be implemented. For the database, we wanted a solution that could scale (obviously) and that would also provide flexibility and consistency. Our existing format, the NCB file, was difficult to modify when new constructs were added (e.g. templates) and the file itself could get corrupted leading our users to delete it periodically if things weren’t working properly in the IDE. We did some research in this area and decided to use SQL Server Compact Edition, which is an in-process, file-oriented database that gives us many of the comforts of working with a SQL database. One of the great things of using something like this is that gave us real indexes and a customizable and constant memory footprint. The NCB on the other hand contained no indexes and was mapped into memory.

Finally, we needed to re-invent our parsers. We quickly realized that the only reasonable solution for scalability was to populate our database incrementally. While this seems obvious at first, it goes against the basic compilation mechanism of C++ in which a small change to a header file can change the meaning of every source file that follows, and indeed every source file in a solution. We wanted to create an IDE where changing a single file did not require reparsing large swaths of a solution, thus causing churn in the database and even possibly locking up the UI (e.g. in the case of loading wizards). We needed a parser that could parse C++ files in isolation, without regard to the context in which they were included. Although C++ is a “context sensitive” language in the strongest sense of the word, we were able to write a “context-free” parser for it that uses heuristics to parse C++ declarations with a high degree of accuracy. We named this our “tag” parser, after a similar parser that was written for good old C code long ago.  We decided to build something fresh in this case as this parser was quite different than a regular C++ parser in its operation, is nearly stand-alone, and involved a lot of innovative ideas. In the future, we’ll talk a bit more about how this parser works and the unique value it provides.

With the core issue of scalability solved, we still needed to build an infrastructure that could provide highly accurate Intellisense information.  To do this, we decided to parse the full “translation unit” (TU) for each open file in the IDE editor* in order to understand the semantics of the code (e.g. getting overload resolution right). Building TUs scales well – in fact, the larger the solution, the smaller the TU is as a percentage of the solution size.  Finally, building TUs allows us to leverage precompiled header technology, thus drastically reducing TU build times.  Using TUs as the basis for Intellisense would yield highly responsive results even in the largest solutions.

Our requirements were clear but the task was significant. We needed rich information about the translation unit in the form of a high-level representation (e.g. AST) and we needed it available while the user was working with the file. We investigated improving on FEACP to achieve this goal but FEACP was a derivation of our compiler, which was not designed for this in mind (see Mark’s post for details). We investigated building a complete compiler front-end designed for this very purpose but this seemed like an ineffective use of our resources. In the 1980s and 1990s, a compiler front-end was cutting-edge technology that every vendor invested in directly but today, innovation lies within providing rich value on top of the compiler. As a result there has been a multiplication of clients for a front-end beyond code generation and we see this trend across all languages: from semantic colorization and Intellisense to refactoring and static analysis. As we wanted to focus on improving the IDE experience, we identified a third and final option: licensing a front-end component for the purposes of the IDE. While this may seem counter-intuitive, it fit well within our design goals for the product. We wanted to spend more resources on the IDE, focusing on scale and richer functionality and we knew of a state-of-the-art component built by the Edison Design Group (commonly referred to as EDG). The EDG front-end fit the bill as it provides a high-level representation chock-full of the information we wanted to build upon to provide insight in the IDE. The bonus is that already handles all of the world’s gnarly C++ code and their team is first in line to keep up with the language standard.

With all these pieces in place, we have been able to build some great new end-to-end functionality in the IDE, which we’ll highlight over the coming weeks. Here’s a sneak peek at one we’ll talk about next week: live error reporting in the editor.

* - We optimize by servicing as many open files as possible with a single translation unit.

Posted by vcblog | 78 Comments

Channel 9 Video: VC 10: Stephan T. Lavavej and Damien Watkins - Inside STL

As Visual Studio 2010 Beta 1was being released, Charles Torre from Channel 9 came over to the Visual C++ team to talk about some of our new features. On this visit he spoke with Stephan T. Lavavej and myself about our VS2010 STL implementation. As Charles says on the Channel 9 page:

 

 “We have already heard about many of the language improvements (auto, decltype, lambdas, rvalue references, …) all of which can be put to good use when using the Standard Template Library (STL). Here  …  tell us all about the latest version of STL. We talk about how the language features are enabling many improvements to the STL, with performance being a big  beneficiary. To realize these benefits we needed to update our STL implementation to leverage these new techniques, for example adding “move” semantics to STL containers. Additionally  when users of our STL implementation add “move” semantics to their types that they store in our STL containers then we hook into these as well.”

 

We hope you enjoy the video and please feel free to post questions/comments on the Channel 9 page – Stephan and I are eager to correspond with our STL users.

 

Thanks

Damien

Posted by vcblog | 5 Comments
Filed under:

STL Breaking Changes in Visual Studio 2010 Beta 1

Visual Studio 2010 Beta 1 is now available for download.  I've recently blogged about how Visual C++ in VS 2010 Beta 1, which I refer to as VC10 Beta 1, contains compiler support for five C++0x core language features: lambdas, auto, static_assert, rvalue references, and decltype.  It also contains a substantially rewritten implementation of the C++ Standard Library, supporting many C++0x standard library features.  In the near future, I'll blog about them in Part 4 and beyond of "C++0x Features in VC10", but today I'm going to talk about the STL changes that have the potential to break existing code, which you'll probably want to know about before playing with the C++0x goodies.

 

 

Problem 1: error C3861: 'back_inserter': identifier not found

 

This program compiles and runs cleanly with VC9 SP1:

 

C:\Temp>type back_inserter.cpp

#include <algorithm>

#include <iostream>

#include <ostream>

#include <vector>

using namespace std;

 

int square(const int n) {

    return n * n;

}

 

int main() {

    vector<int> v;

    v.push_back(11);

    v.push_back(22);

    v.push_back(33);

 

    vector<int> dest;

 

    transform(v.begin(), v.end(), back_inserter(dest), square);

 

    for (vector<int>::const_iterator i = dest.begin(); i != dest.end(); ++i) {

        cout << *i << endl;

    }

}

 

C:\Temp>cl /EHsc /nologo /W4 back_inserter.cpp

back_inserter.cpp

 

C:\Temp>back_inserter

121

484

1089

 

But it fails to compile with VC10 Beta 1:

 

C:\Temp>cl /EHsc /nologo /W4 back_inserter.cpp

back_inserter.cpp

back_inserter.cpp(19) : error C3861: 'back_inserter': identifier not found

 

What's wrong?

 

Solution: #include <iterator>

 

The problem was that back_inserter() was used without including <iterator>.  The C++ Standard Library headers include one another in unspecified ways.  "Unspecified" means that the Standard allows but doesn't require any header X to include any header Y.  Furthermore, implementations (like Visual C++) aren't required to document what they do, and are allowed to change what they do from version to version (or according to the phase of the moon, or anything else).  That's what happened here.  In VC9 SP1, including <algorithm> dragged in <iterator>.  In VC10 Beta 1, <algorithm> doesn't drag in <iterator>.

 

When you use a C++ Standard Library component, you should be careful to include its header (i.e. the header that the Standard says it's supposed to live in).  This makes your code portable and immune to implementation changes like this one.

 

There are probably more places where headers have stopped dragging in other headers, but <iterator> is overwhelmingly the most popular header that people have forgotten to include.

 

Note: Range Insertion and Range Construction

 

By the way, when seq is a vector, deque, or list, instead of writing this:

 

copy(first, last, back_inserter(seq)); // Bad!

 

You should write this:

 

seq.insert(seq.end(), first, last); // Range Insertion - Good!

 

Or, if you're constructing seq, simply write this:

 

vector<T> seq(first, last); // Range Construction - Good!

 

They're not only slightly less typing, they're also significantly more efficient.  copy()-to-back_inserter() calls push_back() repeatedly, which can trigger multiple vector reallocations.  Given forward or better iterators, range insertion and range construction can just count how many elements you've got, and allocate enough space for all of them all at once.  This is also more efficient for deque, and you may as well do it for list too.

 

 

Problem 2: error C2664: 'std::vector<_Ty>::_Inside' : cannot convert parameter 1 from 'IUnknown **' to 'const ATL::CComPtr<T> *'

 

This program compiles and runs cleanly with VC9 SP1:

 

C:\Temp>type vector_ccomptr.cpp

#include <atlcomcli.h>

#include <stddef.h>

#include <iostream>

#include <ostream>

#include <vector>

using namespace std;

 

int main() {

    vector<CComPtr<IUnknown>> v;

 

    v.push_back(NULL);

}

 

C:\Temp>cl /EHsc /nologo /W4 vector_ccomptr.cpp

vector_ccomptr.cpp

 

C:\Temp>vector_ccomptr

 

C:\Temp>

 

But it fails to compile with VC10 Beta 1:

 

C:\Temp>cl /EHsc /nologo /W4 vector_ccomptr.cpp

vector_ccomptr.cpp

C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\vector(623) : error C2664: 'std::vector<_Ty>::_Inside' : cannot convert parameter 1 from 'IUnknown **' to 'const ATL::CComPtr<T> *'

        with

        [

            _Ty=ATL::CComPtr<IUnknown>

        ]

        and

        [

            T=IUnknown

        ]

        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

        C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\vector(622) : while compiling class template member function 'void std::vector<_Ty>::push_back(_Ty &&)'

        with

        [

            _Ty=ATL::CComPtr<IUnknown>

        ]

        vector_ccomptr.cpp(9) : see reference to class template instantiation 'std::vector<_Ty>' being compiled

        with

        [

            _Ty=ATL::CComPtr<IUnknown>

        ]

C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\vector(625) : error C2040: '-' : 'IUnknown **' differs in levels of indirection from 'ATL::CComPtr<T> *'

        with

        [

            T=IUnknown

        ]

 

What's wrong?

 

Solution: Use CAdapt

 

The Standard containers prohibit their elements from overloading the address-of operator.  CComPtr overloads the address-of operator.  Therefore, vector<CComPtr<T>> is forbidden (it triggers undefined behavior).  It happened to work in VC9 SP1, but it doesn't in VC10 Beta 1.  That's because vector now uses the address-of operator in push_back(), among other places.

 

The solution is to use <atlcomcli.h>'s CAdapt, whose only purpose in life is to wrap address-of-overloading types for consumption by Standard containers.  vector<CAdapt<CComPtr<T>>> will compile just fine.  In VC10 Beta 1, I added operator->() to CAdapt, allowing v[i]->Something() to compile unchanged.  However, typically you'll have to make a few other changes when adding CAdapt to your program.  operator.() can't be overloaded, so if you're calling CComPtr's member functions like Release(), you'll need to go through CAdapt's public data member m_T .  For example, v[i].Release() needs to be transformed into v[i].m_T.Release() .  Also, if you're relying on implicit conversions, CAdapt adds an extra layer, which will interfere with them.  Therefore, you may need to explicitly convert things when pushing them back into the vector.

 

 

Problem 3: error C2662: 'NamedNumber::change_name' : cannot convert 'this' pointer from 'const NamedNumber' to 'NamedNumber &'

 

This program compiles and runs cleanly with VC9 SP1:

 

C:\Temp>type std_set.cpp

#include <iostream>

#include <ostream>

#include <set>

#include <string>

using namespace std;

 

class NamedNumber {

public:

    NamedNumber(const string& s, const int n)

        : m_name(s), m_num(n) { }

 

    bool operator<(const NamedNumber& other) const {

        return m_num < other.m_num;

    }

 

    string name() const {

        return m_name;

    }

 

    int num() const {

        return m_num;

    }

 

    void change_name(const string& s) {

        m_name = s;

    }

 

private:

    string m_name;

    int m_num;

};

 

void print(const set<NamedNumber>& s) {

    for (set<NamedNumber>::const_iterator i = s.begin(); i != s.end(); ++i) {

        cout << i->name() << ", " << i->num() << endl;

    }

}

 

int main() {

    set<NamedNumber> s;

 

    s.insert(NamedNumber("Hardy", 1729));

    s.insert(NamedNumber("Fermat", 65537));

    s.insert(NamedNumber("Sophie Germain", 89));

 

    print(s);

 

    cout << "--" << endl;

 

    set<NamedNumber>::iterator i = s.find(NamedNumber("Whatever", 1729));

 

    if (i == s.end()) {

        cout << "OH NO" << endl;

    } else {

        i->change_name("Ramanujan");

    }

 

    print(s);

}

 

C:\Temp>cl /EHsc /nologo /W4 std_set.cpp

std_set.cpp

 

C:\Temp>std_set

Sophie Germain, 89

Hardy, 1729

Fermat, 65537

--

Sophie Germain, 89

Ramanujan, 1729

Fermat, 65537

 

But it fails to compile with VC10 Beta 1:

 

C:\Temp>cl /EHsc /nologo /W4 std_set.cpp

std_set.cpp

std_set.cpp(55) : error C2662: 'NamedNumber::change_name' : cannot convert 'this' pointer from 'const NamedNumber' to 'NamedNumber &'

        Conversion loses qualifiers

 

What's wrong?

 

Solution: Respect set Immutability

 

The problem is modifying set/multiset elements.

 

In C++98/03, you could get away with modifying set/multiset elements as long as you didn't change their ordering.  (Actually changing their ordering is definitely crashtrocity, breaking the data structure's invariants.)

 

C++0x rightly decided that this was really dangerous and wrong.  Instead, it flat-out says that "Keys in an associative container are immutable" (N2857 23.2.4/5) and "For [set and multiset], both iterator and const_iterator are constant iterators" (/6).

 

VC10 Beta 1 enforces the C++0x rules.

 

There are many alternatives to modifying set/multiset elements.

 

·        You can use map/multimap, separating the immutable key and modifiable value parts.

 

·        You can copy, modify, erase(), and re-insert() elements.  (Keep exception safety and iterator invalidation in mind.)

 

·        You can use set/multiset<shared_ptr<T>, comparator>, being careful to preserve the ordering and proving once again that anything can be solved with an extra layer of indirection.

 

·        You can use mutable members (weird) or const_cast (evil), being careful to preserve the ordering.  I strongly recommend against this.

 

I should probably mention, before someone else discovers it, that in VC10 Beta 1 we've got a macro called _HAS_IMMUTABLE_SETS .  Defining it to 0 project-wide will prevent this C++0x rule from being enforced.  However, I should also mention that _HAS_IMMUTABLE_SETS is going to be removed after Beta 1.  You can use it as a temporary workaround, but not as a permanent one.

 

 

Problem 4: Specializing stdext::hash_compare

 

If you've used the non-Standard <hash_set> or <hash_map> and specialized stdext::hash_compare for your own types, this won't work anymore, because we've moved it to namespace std.  <hash_set> and <hash_map> are still non-Standard, but putting them in namespace stdext wasn't accomplishing very much.

 

Solution: Use <unordered_set> or <unordered_map>

 

TR1/C++0x <unordered_set> and <unordered_map> are powered by the same machinery as <hash_set> and <hash_map>, but the unordered containers have a superior modern interface.  In particular, providing hash and equality functors is easier.

 

If you still want to use <hash_set> and <hash_map>, you can specialize std::hash_compare, which is where it now lives.  Or you can provide your own traits class.

 

By the way, for those specializing TR1/C++0x components, you should be aware that they still live in std::tr1 and are dragged into std with using-declarations.  Eventually (after VC10) this will change.

 

 

This isn't an exhaustive list, but these are the most common issues that we've encountered.  Now that you know about them, your upgrading experience should be more pleasant.

 

Stephan T. Lavavej

Visual C++ Libraries Developer

Posted by vcblog | 13 Comments

/DYNAMICBASE and /NXCOMPAT

Hello, my name is Xiang Fan and I am a developer on the C++ Shanghai team.

Today I’d like to talk about two linker options related to security: /DYNAMICBASE and /NXCOMPAT.

 

These two options are introduced in VS2005, and target to improve the overall security of native applications.

 

You can set these two options explicitly in VS IDE:

 

 

These two options have three available values in the IDE: On, Off and Default.

 

They are set to “On” if you create native C++ application using VS2008 wizard.

When VS2008 upgrades projects created by older version of VC which doesn’t support these options, it will set them to “Off” after upgrade.

If you set them to “Default”, linker will treat it as “Off”.

 

After several years adoption, we plan to change the behavior of “Default” to “On” in VS2010 to reinforce the security. And we’d like to get your feedback.

 

Here are the detailed information about these two options:

 

1.      DYNAMICBASE

 

/DYNAMICBASE modifies the header of an executable to indicate whether the application should be randomly rebased at load time by the OS. The random rebase is well known as ASLR (Address space layout randomization).

This option also implies “/FIXED:NO”, which will generate a relocation section in the executable. See /FIXED for more information.

 

In VS2008, this option is on by default if a component requires Windows Vista (/SUBSYSTEM 6.0 and greater)

/DYNAMICBASE:NO can be used to explicitly disable the random rebase.

 

This article talks about ASLR: http://technet.microsoft.com/en-us/magazine/cc162458.aspx

ASLR is supported only on Windows Vista and later operating systems. It will be ignored on older OS.

 

ASLR is transparent to the application. With ASLR, the only difference is OS will rebase the executable unconditionally instead of doing it only when an image base conflict exists.

 

2.      NXCOMPAT

 

/NXCOMPAT is used to specify an executable as compatible with DEP (Data Execution Prevention)

Notice that, this option applies for x86 executable only. Non-x86 architecture versions of desktop Windows (e.g. x64 and IA64) always enforce DEP if the executable is not running in WOW64 mode.

 

Here is a comprehensive description of DEP:

http://support.microsoft.com/kb/875352

 

This option is on by default if a component requires Windows Vista (/SUBSYSTEM 6.0 and greater).

/NXCOMPAT:NO can be used to explicitly specify an executable as not compatible with DEP.

However, the administrator can still enable the DEP even if the executable is not specified as compatible with DEP. So you should always test your application with DEP on.

 

Windows Vista SP1, Windows XP SP3 and Windows Server 2008 add a new API SetProcessDEPPolicy to allow the developer to set DEP on their process at runtime rather than using linker options. See the following link for more details:

http://blogs.msdn.com/michael_howard/archive/2008/01/29/new-nx-apis-added-to-windows-vista-sp1-windows-xp-sp3-and-windows-server-2008.aspx

 

There are several common (and incomplete) patterns which are not compatible with DEP (See http://msdn.microsoft.com/en-us/library/aa366553.aspx for more information.)

a.       Dynamic code generated in heap or stack

If your application must run code from a memory page, it must allocate and set the proper virtual memory protection attributes.

 

The allocated memory must be marked PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, or PAGE_EXECUTE_WRITECOPY when allocating memory. Heap allocations made by calling the new, malloc and HeapAlloc functions are non-executable. An application can use the VirtualAlloc function to allocate executable memory with the appropriate memory protection options.

 

Another option is to pass HEAP_CREATE_ENABLE_EXECUTE when create the heap via  HeapCreate. Then the memory allocated by the subsequent HeapAlloc will be executable.

 

b.      Executable code in data section

They should be migrated to a code section

 

Security vulnerabilities are more exploitable than they would be if DEP were enabled. So you should always make your application DEP compatible and turn DEP on.

 

The following sample demonstrates the code which is not compatible with DEP.

It also shows two DEP compatible ways to run the code on heap.

Running code in data section or on stack almost always implies security holes. You have to put the code in code section or heap instead.

 

#include "windows.h"

#include <cstdio>

 

typedef void (*funType)();

unsigned char gCode[] = {0xC3}; // ”ret” instruction on x86

const size_t gCodeSize = sizeof(gCode);

 

// these are not DEP compatible

 

void RunCodeOnHeap()

{

    unsigned char *code = new unsigned char[gCodeSize];

    memcpy(code, gCode, gCodeSize);

 

    funType fun = reinterpret_cast<funType>(code);

    fun();

 

    delete []code;

}

 

// these are DEP compatible

 

void RunCodeOnHeapCompatible1()

{

    unsigned char *code = (unsigned char *)::VirtualAlloc(NULL, gCodeSize, MEM_COMMIT, PAGE_READWRITE);

    memcpy(code, gCode, gCodeSize);

 

    DWORD flOldProtect;

    ::VirtualProtect(code, gCodeSize, PAGE_EXECUTE_READ, &flOldProtect);

 

    funType fun = reinterpret_cast<funType>(code);

    fun();

 

    ::VirtualFree(code, 0, MEM_RELEASE);

}

void RunCodeOnHeapCompatible2()

{

    HANDLE hheap = ::HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);

 

    unsigned char *code = (unsigned char *)::HeapAlloc(hheap, 0, gCodeSize);

    memcpy(code, gCode, gCodeSize);

 

    funType fun = reinterpret_cast<funType>(code);

    fun();

 

    ::HeapFree(hheap, 0, code);

    ::HeapDestroy(hheap);

}

 

INT DEPExceptionFilter(LPEXCEPTION_POINTERS lpInfo)

{

    // please check http://technet.microsoft.com/en-us/library/bb457155.aspx

    // for more information

 

    if (lpInfo->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION &&

        lpInfo->ExceptionRecord->ExceptionInformation[0] == 8) {

        return EXCEPTION_EXECUTE_HANDLER;

    }

 

    return EXCEPTION_CONTINUE_SEARCH;

}

 

int main()

{

    __try

    {

        RunCodeOnHeap();

        printf("RunCodeOnHeap: OK\n");

    }

    __except (DEPExceptionFilter(GetExceptionInformation()))

    {

        printf("RunCodeOnHeap: Fail due to DEP\n");

    }

    __try

    {

        RunCodeOnHeapCompatible1();

        printf("RunCodeOnHeapCompatible1: OK\n");

    }

    __except (DEPExceptionFilter(GetExceptionInformation()))

    {

        printf("RunCodeOnHeapCompatible1: Fail due to DEP\n");

    }

    __try

    {

        RunCodeOnHeapCompatible2();

        printf("RunCodeOnHeapCompatible2: OK\n");

    }

    __except (DEPExceptionFilter(GetExceptionInformation()))

    {

        printf("RunCodeOnHeapCompatible2: Fail due to DEP\n");

    }

}

 

Output:

 

cl test.cpp /link /nxcompat:no

 

RunCodeOnHeap: OK

RunCodeOnHeapCompatible1: OK

RunCodeOnHeapCompatible2: OK

 

cl test.cpp /link /nxcompat

 

RunCodeOnHeap: Fail due to DEP

RunCodeOnHeapCompatible1: OK

RunCodeOnHeapCompatible2: OK

 

In summary, “cl test.cpp” is equivalent to “cl test.cpp /link /nxcompat:no /dynamicbase:no” before VS2010. We plan to change it to “cl test.cpp /link /nxcompat /dynamicbase” in VS2010.

If you have any concerns about the default behavior change of these two options, don’t hesitate to give your feedback. Thanks!

 

Regards,

    Xiang

Posted by vcblog | 5 Comments

Using the Windows 7 RC SDK in Visual C++ 2010 Beta 1

Though the Windows 7 RC SDK was released about 2 weeks before Visual Studio 2010 Beta 1, it was not possible to incorporate that release into VS 2010 Beta 1. As a result, the Windows SDK components that ship as part of Visual Studio 2010 Beta 1 are the Windows 7 Beta SDK versions.

This post will describe how you can use the Native Multitargeting feature in Visual Studio 2010 to compile and link your applications against the Windows SDK supporting Windows 7 RC.

Step 1: Download and install the RC SDK from http://www.microsoft.com/downloads/details.aspx?familyid=F75F2CA8-C1E4-4801-9281-2F5F28F12DBD&displaylang=en

Step 2: Add the Windows 7 SDK as a platform target to Visual Studio:

  • a) Download the Windows7SDK.zip file attached to this blog post.
  • b) Extract the zip file into The Program Files directory (On 64 bit versions of Windows into the Program Files (x86) directory) by opening it up in Explorer and selecting Extract All Files. In the dialog select the appropriate directory. If you are unsure what the Program Files Directory is on your system, you can type %ProgramFiles% (or %ProgramFiles(x86)% for a 64 bit OS) into the Address bar of an Explorer window and press enter. The Address bar will then show the correct path that you can copy and paste. Extract, then answer yes to the question about merging contents of the directories.
  • c) After the extract, verify that the directory %ProgramFiles%\ MSBuild\Microsoft.Cpp\v4.0\Platforms\Win32\PlatformToolsets\Windows7SDK was created and contains the following 2 files: Microsoft.Cpp.Win32.Windows7SDK.props and Microsoft.Cpp.Win32.Windows7SDK.targets. (For a 64 bit OS, the directory should start at %ProgramFiles(x86)%).

For each project that you want to target at the RC version of the Windows 7 SDK do the following:

  • 1) Open the Solution containing the project.
  • 2) Right Click the Project node in the Solution Explorer pane and select Properties.
  • 3) Select the Configuration Properties, General from the list in the left pane.
  • 4) Select All Configurations in the Configuration dropdown.
  • 5) Select Windows7SDK in the Platform Toolset option in the right pane under the General category.

Note that the platform configuration we added is just for developing 32-bit applications. One could create a similar Platform for X64 builds, but these are not included here.

We have verified basic correctness, but have not run a comprehensive set of test cases. More specifically this is the level of correctness testing we have done:

Built an MFC app and a Windows Forms app with Dev10 targeting v100
Built an MFC app and a Windows Forms app with Dev10 + WinSDK toolset targeting v100
Built an MFC app and a Windows Forms app with Dev10 + WinSDK toolset targeting WinSDK7RC
Built an MFC app and a Windows Forms app WinForms with Dev10 + WinSDK toolset + WinSDK RC installed and targeting v100
Built an MFC app and a Windows Forms app with Dev10 + WinSDK toolset + WinSDK RC installed and targeting WinSDK7RC

Note that some Windows 7 RC SDK samples do not build in Visual Studio 2010 Beta 1. We are investigating these issues and will publish information about this on the Windows SDK team blog as it becomes available.

We will also be posting specifically about Native Multitargeting in detail in the next couple weeks on the Visual C++ blog. If you are interested in some background information before that, please take a look at the following entry on Soma's blog giving a brief overview: http://blogs.msdn.com/somasegar/archive/2008/11/21/c-enhancements-in-vs-2010.aspx

Posted by vcblog | 12 Comments

Attachment(s): Windows7SDK.ZIP
More Posts Next page »
 
Page view tracker