Advertisement

Visual studio: "edit and continue" not working properly

Started by October 07, 2017 04:45 PM
9 comments, last by Hodgman 6 years, 11 months ago

Hi

Im confused about the "edit and continue" feature. It didn't give me problem in VS 2008. Now running VS C++ 2013.

Im changing things like a constant in a function call and Visual studio refuses to "edit and continue" that. Example:


gfx.pictureCircular(pos2.x - 12, pos2.y + 35, rrr.symbol[12], 1 - (reloadDelay / JAM_TIME), 0.5, RED(100), BLEND_LIGHT);

Changing only "- 12 " to "-10" will give me:


Error	2	Edit and Continue does not support changes to data types; build required	c:\program files (x86)\microsoft visual studio 12.0\vc\include\list	773	
Error	3	Build errors occurred.	Project	

I didnt change anything in any files in "include/list". Just this change above that is in a file in my project. 

Strange thing is sometimes it allows me to change something like that. What am I missing? I really like this feature and want it to work!
Thanks
Erik

On 10/7/2017 at 11:45 AM, suliman said:

Strange thing is sometimes it allows me to change something like that. What am I missing? I really like this feature and want it to work!

The trick is understanding what can be changed while running and what cannot.

Internally the magic works by hot-swapping out parts of a function body which is done by a little padding secretly added by the compiler when the code is built. That is the key to remember.  Over time you can figure out what items inside a function body can be swapped out and and what cannot.

Internally on each function the compiler adds a little padding, then it replaces or modifies the padding with one of several options to accommodate your change. Maybe it will a jump to a new location for the hot-swapped code, returning back to the end of the padding when finished, or use it for space for your new variables, or maybe some other options depending on your change.

You cannot make changes that are outside a function body, like adding or removing a function, adding a global variable, or modifying a signature such as changing parameters the function takes.  Essentially these are adding a completely new item so there is no existing padding to modify.

You can add some variables inside a function body, but anything more than fundamental types that the compiler understands has a risk of having issues. Also the amount of space to hot-swap in a function is limited, you can only add a small number of stack-allocated objects.  The details has to do with how much padding was added to enable edit and continue to work, and how much padding is available to be used for those variables. If you're adding an object requiring 32 bytes and only 16 bytes of padding remain, you will need to recompile.

There are limits on changing functions that you're currently calling or inside of.  If the system thinks you are modifying a function in the call stack, it probably won't let you. If you can cope with the side effects of the code you might be able to step out of the function, make the change, then move the instruction pointer back to the function to call it again. 

You also can't make changes in code that is scattered rather than a single location. Functions that have been inlined, certain lambda uses, or template code that gets generated under the hood, these are not proper function bodies with little bits of padding around them. If they are scattered then the code can't be easily distributed.  If they don't have the little block of padding they don't have the ability to be hot-swapped. Either way, those changes are out.

 

But if you follow the rules, only modify the internals of a function with new calls and limit the amount of new variables being created, it should work okay.

 

From what you described for your change, it doesn't look like that renumbering would modify the object type, so there is probably more than you included in your post that is critical.  If the change did modify the type (and the compiler would know immediately if that was the case) then it would require changing a signature, and changing signatures is beyond the scope of the system.

Advertisement

Thanks for the comprehensive info!
However i then do not understand why my change above (and others like it) is not acceptable. The param input i changed is a simple "int" (x-position), this is the only version of the function (gui::pictureCircular). Im also not inside the function when i change it.

But above all, i NEVER had any problem with this in VS 2008. Is there a setting that makes "edit and continue" more sensitive? I'd rather have the behaviour of VS 2008 in my current VS (2013), even though this new behaviour is somehow "safer". I now have to recompile almost any change, such as the one described above (very often changes are adjusting GUI-placement  (posx, posy) which i think should be fine to change).

Your error message says something different than what you write.

On 10/7/2017 at 11:45 AM, suliman said:

Error 2 Edit and Continue does not support changes to data types; build required c:\program files (x86)\microsoft visual studio 12.0\vc\include\list 773 

If you want to diagnose why it happens, you'll need to provide more code.  A link to the actual source file would be best. 

I don't have VC12 installed, but you or someone who does could probably look up what is going on in line 773 of the standard library's list, then figure out how that relates to the line you're changing.  If you are only changing one integer to a different integer, maybe you're in a lambda, or maybe inside a template or inlined function as mentioned earlier, or maybe something else is going on.

Without more information we can only guess.

Are you sure the 12 is an integer?  If it's being promoted to a float, then I might be able to explain why edit and continue is choking:

The assembly code to deal with integer constants can just use an 'immediate' operand - these are values embedded with the GPR instructions themselves.  However, floating point's FLD instruction doesn't have an immediate version.  They load from memory addresses.  There are also a handful of load-common-constant instructions (0, 1, pi, etc), but none of those matter for your case.

What I've seen the compiler do with float constants is it bakes them into the static initialized data region of the EXE/DLL.  I'm not sure whether it considers the floating point constant table to be a data structure of its own, but if it does that may explain why you're getting that error message.


if (playerDist(p, true) > 200){

}

This for example gives me the error (changing the constant 100 to 200). That cannot be interpreted as a float right? Or does it count as a float since it compares with the left side of ">"? The function playerDist returns a float.

Advertisement

It's possible the compiler may have changed that constant to a float ahead of time (because otherwise it would have to make some assembly that converts it at runtime)

Is it possible to instruct the compiler to always just use these as integers? (if that would allow such changes to not invalidate "edit and continue"). I'm asking becouse again, this used to not be a problem in earlier versions of visual studio c++ and I have these constants (integers) EVERYWHERE and I often change them.

Extracting the value as a conversion into a new variable before the comparison would probably do it. You could do it before the statement in the non edit-and-continue compilation, as creating new variables is typically invalid under edit-and-continue.

On 12/3/2017 at 7:11 AM, suliman said:


if (playerDist(p, true) > 200){

}

This for example gives me the error (changing the constant 100 to 200). That cannot be interpreted as a float right? Or does it count as a float since it compares with the left side of ">"? The function playerDist returns a float.

Use:


static float threshold = 200;
if (playerDist(p, true) > threshold){

}

Then you don't even need edit and continue. You can set a breakpoint there, mouse over 'threshold', change the value, then continue. Even when E&C is working, this way is still faster (plus it also works when E&C poops its pants).

This topic is closed to new replies.

Advertisement