0

I upgraded to the latest version of VisualStudio 2017 (15.9.5) to compile our native C++ application. However now in Release mode (and only in Release) I get the following warning (and we treat warnings as errors):

...nothing useful...
6>qrc_IceApplication.cpp
6>   Creating library C:/tkbt/Prose/Build/Release/lib/Prose.lib and object  C:/tkbt/Prose/Build/Release/lib/Prose.exp
6>Generating code
6>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\functional(1195): error C2220: warning treated as error - no 'executable' file generated
6>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\functional(1195): warning C4789: buffer '_Temp' of size 64 bytes will be overrun; 72 bytes will be written starting at offset 8
6>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\functional(1195): warning C4789: buffer '_Temp' of size 64 bytes will be overrun; 72 bytes will be written starting at offset 8
6>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\functional(1195): warning C4789: buffer '_Temp' of size 64 bytes will be overrun; 72 bytes will be written starting at offset 8
6>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\functional(1195): warning C4789: buffer 'DetectPossibilities' of size 64 bytes will be overrun; 72 bytes will be written starting at offset 8
6>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\functional(1195): warning C4789: buffer '_Temp' of size 64 bytes will be overrun; 72 bytes will be written starting at offset 8

DetectPossibilities is the only thing that has any relation to our code (_Temp does not), and the only thing I can see that is odd is that it is self capturing

std::function<bool(int)> DetectPossibilities;
DetectPossibilities = [&](int startPos) -> bool { 
   ... lots of code
   bool nestedAnyFound = DetectPossibilities(startPos + ofMatch.capturedLength());
   ... lots of code
};

UPDATE: I've found a workaround, and a plausible explanation, so I'm going to post the Q and the A so that the next person doesn't spend the same half-day I did to work out what's going on.

gremwell
  • 1,419
  • 17
  • 23

1 Answers1

0

Here's our theory about what might be happening under the hood:

std::function<bool(int)> DetectPossibilities;

Compiles (in release mode) to something equivalent to a 64 bytes allocation in memory.

DetectPossibilities = [&](int startPos) -> bool { 

Assigns a new lambda to it, this one has a capture, and this compiles (in release mode) 72 bytes of memory, but does not fit into the same spot in memory, hence the warning. The only difference is the capture. So if we make sure the original also has the capture, then we should be able to get around this strange issue.

  std::function<bool(int)> DetectPossibilities = [&](bool){return 0;};
  DetectPossibilities = [&](int startPos) -> bool {

Indeed this links in release mode, avoiding those strange errors.

Seems like a bug in Visual Studio to me, because it doesn't happen in a debug compile, and a compiler should have the smarts to be able to handle that particular pattern and allocate memory correctly.

gremwell
  • 1,419
  • 17
  • 23
  • 2
    Seems like you might still be linking with an old lib or obj that was built with the older VS. This fix shouldn't have any impact. In c++ no object's size can depend on how it was initialized. It only depends on it's type. Check `DetectPossibilities`'s size and if it differs at different point you probably have an ABI incompatibigy error. – François Andrieux Jan 10 '19 at 04:01
  • 2
    Actually, it might be something as simple as having one component of the solution building with the wrong configuration. Might be worth checking all the configuration, specially if you upgraded your project files for VS2017 recently. – François Andrieux Jan 10 '19 at 04:05
  • Good thoughts, however this is in a class defined entirely within the cpp, so really there should be just the one compilation unit using it. Of course I had tried rebuild all several times (our build system was actually the thing that picked it up after we upgraded it's VS version). Also, dunno if anyone noticed, but I assigned it a wrong. It's declared bool(int) and I assign it a int(bool) but it doesn't give two hoots! – gremwell Jan 11 '19 at 10:11
  • "This fix shouldn't have any impact." And yet it did! It's not something local either, as this happened on all machines that had upgraded visual studio. If I remove the assignment, the warning comes back. It really does feel like a problem with the latest VS. – gremwell Jan 11 '19 at 10:18
  • Well, then it might be a compiler bug. Please share a [MCVE] so that other users may verify that. The fact that it's reproducible on other systems doesn't rule out a project configuration error since you presumably test using the same project files. – François Andrieux Jan 11 '19 at 11:34