Hello, I'm using Composer XE 2013.1.119. There is some code in assembler in our C++ projects and I get the following warning:
warning #15139: instruction saving a non-volatile register will not be unwound in the event of an exception.
Some of our functions/methods use a lot of assembler to speed up the process. But they generate this warning. I don't know how to solve it. I'm not sure about its signification. My guess is that the (assembler) instructions save a cpu register that is used to pass parameters. If these registers are modified, the program won't be able to unwind the call stack on an exception??? Am I right? If so, which registers are they? How to use them whithout generating this warning? Notice that I did not code these methods neither I'm a guru in __asm.
Thanks for you help!
I cannot send you a piece of code since it is the core of our software. But I found something interesting. Maybe you can confirm my suspicions. The warning occurs when there is:
where xxx is a non-volatile register (RBX, R12-R15, RDI, RSI, RBP, RSP). I'm a newbie in assembler but maybe "pushing" a non-volatile register could forbid the stack to be unwound?
Microsoft unwinding doesn't allow modification of the stack pointer (RSP) after fixed stack allocation happening on entry to a routine using RSP-base frame. There is just no way to specify such kind of action in the unwind tables.
For example, if your routine consists of the following instructions:
sub rsp, 40
;; inline asm begin
sub rsp, 4
add rsp, 4
;; inline asm end
add rsp, 40
A compiler won't be able to encode actions executed by "sub/add rsp, 4" into the unwind tables. Thus if <some code> generates an exception, RSP after the stack of this routine is unwinded will be off by 4, which may cause run-time problems in your program.
PUSH is just another instruction that decrements value of RSP register, so it may result in the same problems. And I agree that the warning message is misleading. There is another warning "#15138: instruction allocating stack space will not be unwound in the event of an exception" that describes the problem more accurately. We will try to fix this in one of next releases.
I would like to understand why you need to save original value of some non-volatile register. It shouldn't be required usually. If your code (either inline asm or C/C++ code) clobbers/changes original value of a non-volatile register, the compiler will save the original value on entry to the routine and restore it on exit. Along with that the compiler will generate proper unwinding tables containing information about how to restore the register in case of an exception. So you usually do not need to use explicit PUSH/POP instructions. Could you please explain why you need it?
Looking forward to your comments!
Many thanks for your help! My present job is to port a MSVS2005/ICC9.1 to MSVS2012/ICC13.0 solution with many projects. Many (new) warnings appeared will building the solution and I try to fix them because they can be very anoing (I got something like 20000 warnings!) Many of them are fixed now but this one remained a mystery. Now we solved it. I cannot tell you why the assembly code was like this because it was written long time ago by another developper.
I am glad to hear that you were able to rewrite your code and avoid the warning. Your program is more reliable now, which is what this warning was meant to help you to achive.