Closed horenmar closed 7 months ago
According to the MSVC docs, there are other /EH
flags, /EHa
and /EHr
(respectively, enabling asynchronous exception handling and enabling generation of runtime termination checks). But it also seems like, according to this StackOverflow question at least, exceptions will be enabled if you have any try
-catch
in your code (including even if you don't use any in your code but you #include
an STL header file which most likely does). So I'm guessing we do need the flags to disable exception handling after all, and we need to have /EHa- /EHs- /EHr-
.
Either way, we need to properly make sure that the generated binaries actually are devoid of exception handling. I think I missed that step last time, but I don't remember.
So I found this post covering exceptions on MSVC.
If I compile the example snippet in the post with cl ex.cpp
, I get the same warning: warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
. If I compile it with cl /EHsc ex.cpp
, the warning goes away.
If I try it with cl /EHs- ex.cpp
, I get the warning again. So this seems to me to indicate that you can't actually disable exceptions entirely by using /EHs-
. And lastly, trying cl /EHs- /EHa- /EHr- ex.cpp
results in...
cl : Command line warning D9007 : '/Ehr' requires '/Eha, /EHs or /GX'; option ignored
cl : Command line warning D9002 : ignoring unknown option '/EH-'
...and still produces warning C4530.
So no, removing /EHsc
or adding /EHs-
doesn't work.
I mean
// ehsc.test.cpp
#include <cstdlib>
#include <vector>
void sink(std::vector<int> const& s);
int main(int argc, char** argv) {
std::vector<int> vec; vec.reserve(argc);
for (int i = 0; i < argc; ++i) {
vec.push_back(atoi(argv[argc]));
}
sink(vec);
}
> cl /c ehsc.test.cpp /Fo"ehsc.enabled.o" /EHsc
> cl /c ehsc.test.cpp /Fo"ehsc.disabled.o" /EHs-c-
> cl /c ehsc.test.cpp /Fo"ehsc.disabled.full.o" /EHs-c- /D_HAS_EXCEPTIONS=0
> dir
24.02.2024 21:18 <DIR> .
24.02.2024 21:18 <DIR> ..
24.02.2024 21:20 27 429 ehsc.disabled.full.o
24.02.2024 21:20 29 438 ehsc.disabled.o
24.02.2024 21:20 27 854 ehsc.enabled.o
24.02.2024 21:16 269 ehsc.test.cpp
I mean
So we should have been using /D_HAS_EXCEPTIONS=0
all this time?
/EHs-
(or /EHs-c-
if you want to be more explicit) tells the compiler to not bother generating exception related data/code, e.g. info for stack unwinding./D_HAS_EXCEPTIONS=0
tells the stdlib to compile without exceptions (disables try
, catch
, etc)./MT
, /MTd
)
/EHs-
(or/EHs-c-
if you want to be more explicit) tells the compiler to not bother generating exception related data/code, e.g. info for stack unwinding.
As I established above, /EHs-
doesn't actually do anything unless there was a /EHs
before (and we already remove all such flags first just to be sure).
/D_HAS_EXCEPTIONS=0
tells the stdlib to compile without exceptions (disablestry
,catch
, etc).
I figured. I'll look into this more. This might be what we were looking for in the first place.
- Without exceptions it is also preferable to link to the static version of the runtime libs. (
/MT
,/MTd
)
We already do this.
(and we already remove all such flags first just to be sure).
(and we already remove all such flags first just to be sure).
Yes, we do. The string(...)
removes all flags. The set(...)
does add /EHsc
, and yes, that still results in some exception support, but replacing /EHsc
with /EHs-
or removing the set(...)
would not disable exceptions.
The CMake code that is supposed to disable exceptions for MSVC build instead enables fully conforming exception handling. The correct approach is to justnot have any
/EH
flags at all, but if you want to be explicit about it you can add/EHs-
instead.https://github.com/TerryCavanagh/VVVVVV/blob/8dd5414e8defb6c0bc425acb22c25215012615aa/desktop_version/CMakeLists.txt#L290-L292