My code looks like this:
#include <stdio.h>
#pragma pack(1)
class MyClass
{
bool a;
bool b;
int c;
char d[3];
bool e[4];
};
#pragma pack()
int main()
{
printf("sizeof(MyClass)=%d\n", sizeof(MyClass));
return 0;
}
The output is:
sizeof(MyClass)=13
But when I "hover" over sizeof(MyClass) I get:
This wouldn't have been a big issue but I'm trying to implement a compile-time assertion and it isn't working (getting a red underline):
Anyone have any idea how to fix this?
This is not a difference between compile-time and run-time; it is a difference between your compiler and your IDE's "intellisense", the latter of which appears not to support/recognise the #pragma pack directive.
Ignore it. The size is 13.
Since you can actually build your program, you know that the compile-time assertion succeeds, despite the "red line".
It is probably worth adding a comment before that assertion, explaining that users of Visual Studio 2015 will see a false negative in their IDE for the following assertion.
You may also wish to raise a bug on Microsoft Connect, if there is not one already.
Related
I'm trying to investigate the difference in generated code when I switch Visual Studio 2019 from /EHsc (Structured and C++ exceptions only) to /EHs (also do not assume that extern "C" functions won't throw – ref), but I can't seem to coax VS into providing a useful testcase when I've minimised it.
I'm surprised the following doesn't do it (the assembly in both cases is identical), since the contents of the function referred to by fptr (a possible definition being included in comments for exposition) are unknown to the optimiser.
void foo();
/*void foo()
{
throw 0;
}*/
extern "C"
void bar(void (*fptr)())
{
fptr();
}
int main()
{
try
{
bar(&foo);
}
catch (...) {}
}
Granted, it knows that any hypothetical exception will be immediately caught, and since with /EHsc the result of this exception propagation is "undefined" per Microsoft, it "appearing to work" is of course a valid outcome. But that's not much help to me here!
So how can I perform this experiment, without introducing different translation units? Ideally I want to be able to come up with a Compiler Explorer snippet for this.
My goal is to prove that permitting extern "C" to throw (or, rather, propagate) C++ exceptions in a well-defined manner does not have a higher runtime cost than I'm willing to accept in trade.
Yes, I am aware of general advice not to let exceptions cross module boundaries or flow through third-party C code. Yes, I am doing that anyway. Yes, that's fine in our project! 😊
The following MCVE may give you some ideas for a test framework. You could easily add more 'thorough' test code, but this will compile and run. Note that, with the /EHsc option set, this warning is generated:
warning C5039: 'FuncTst': pointer or reference to potentially throwing
function passed to extern C function under -EHc. Undefined behavior
may occur if this function throws an exception.
However, when using /EHs the warning goes away - which suggests at least the possibility of different code generation.
Here's the suggested code:
#pragma warning(disable:4514) // These two lines de-fluff the hundreds of other
#pragma warning(disable:4710) // warning generated when /Wall is used.
#include <iostream>
using pFunc = int(__stdcall*)(int);
extern int __stdcall FuncOne(int p) {
int answer = 0;
for (int i = 0; i < p; ++i) answer += i / p; // Possible divide-by-zero
return answer;
}
extern "C" int __stdcall FuncTst(int i, pFunc fnc) noexcept // Expects noexcept but "FuncOne" can throw!
{
return fnc(i);
}
int main()
{
int q;
std::cout << "Enter test number: ";
std::cin >> q;
int z = FuncTst(q, FuncOne);
std::cout << "Result = " << z << std::endl;
return 0;
}
Hope it helps! Feel free to offer critique and/or ask for any 'improvements' or explanation.
Note: Although you can't specifically enable the C5039 warning when you compile with (say) \W4, you can force it to flag as an error (though this may be a bit harsh), with:
#pragma warning(error:5039)
This seems a sort of bug on Compiler Explorer, that forces /EHc even if /EHs is explicitly set.
Try to compile this code on some MSVC version with /EHs:
extern "C" void foo() {
throw 1;
}
static_assert(noexcept(foo()), "");
Surprisingly, the function foo is assumed noexcept, and the compiler output states the reason:
example.cpp (2): warning C4297: 'foo': function assumed not to
throw an exception but does (2): note: The function is extern
"C" and /EHc was specified
Here you can find this test. You may also see this by adding something like throw 1; in your example.
Nevertheless, you can fix it compiling with /EHc- /EHs (also replace /O3 with /O2, as it is not supported on MSVC), but the output is still the same.
You can find your example, fixed, here. In the /EHc- /EHs case, the output states
cl : Command line warning D9025 : overriding '/EHc' with '/EHc-'
and a static assertion will state that bar is actually not assumed noexcept.
Yesterday I asked a question about this problem, but I wasn't able to give a MVCE. I've managed to reproduce this with a simple program. The problem is with using an std::list as a static inline declaration in a class. Microsoft Visual Studio does support this new C++17 feature. It had some bugs as of March, but as far as I know they've been fixed since. Here are instructions of how I can get this problem, this happens in debug mode.
In main.cpp
#include <iostream>
#include "header1.h"
int main()
{
return 0;
}
In header1.h:
#include <list>
struct Boo
{
static inline std::list<int> mylist;
};
In anotherCPP.cpp
#include "Header1.h"
When the program exits main() it destroys all the static objects and throws an exception.
If this doesn't crash, maybe on your system the compiler/linker optimised some code out, so you can try making main.cpp and anotherCPP.cpp do something. In anotherCPP.cpp:
#include <iostream>
#include "Header1.h"
void aFunction()
{
std::cout << Boo::mylist.size();
}
And make main.cpp:
#include <iostream>
#include "Header1.h"
void aFunction();
int main()
{
std::cout << Boo::mylist.size();
afunction();
return 0;
}
When the program exits I get an exception here when the std::list is being cleared. Here is the Visual Studio debug code where it crashes:
for (_Nodeptr _Pnext; _Pnode != this->_Myhead(); _Pnode = _Pnext)
{ // delete an element
_Pnext = _Pnode->_Next; // Here: Exception thrown:
// read access violation.
// _Pnode was 0xFFFFFFFFFFFFFFFF.
this->_Freenode(_Pnode);
}
This happens only if I declare the static inline std::list< int > mylist in the class. If I declare it as static std::list< int > mylist in my class and then define it separately in one .cpp as std::list< int > Boo::mylist; it works fine. This problem arises when I declare the std::list static inline and I include the header for the class in two .cpp files.
In my project I have stepped through the std::list clear loop from above, I took note of the "this" pointer address. I stepped through the loop as it freed nodes in my list. It then came back to free other std::lists, including in std::unordered_map (as they also use std::lists from the looks of it). Finally when the read access exception is thrown and _Pnode is an invalid pointer address, I noticed the "this" pointer address is the same as the "this" pointer address when clearing std::list< int > mylist, which makes me think that it's trying to delete it twice, and probably why it's crashing.
I hope someone can reproduce this, I'm not sure what this is, if it's a bug or something I'm doing wrong. Also this happens for me in 32 and 64 bit, but only in debug mode, because the node freeing loop I provided is under a macro:
#if _ITERATOR_DEBUG_LEVEL == 2
This issue was filed as a bug here under the title "Multiple initializations of inline static data member in Debug mode".
This was found in Visual Studio 2017 version 15.7.
The VS compiler team has accepted this and have fixed the problem in an upcoming release.
When I try to compile the following C code on Visual Studio 2017 with default C/C++ settings:
#include <stdio.h>
#include <stdlib.h>
/* function declaration */
/*Line 6*/ int max(int num1, int num2, int num3);
int main() {
/* local variable definition */
int a = 100;
int b = 200;
int c = 400;
int ret;
/* calling a function to get max value */
ret = max(a, b, c);
printf("Max value is : %d\n", ret);
return 0;
}
/* function returning the max between two numbers */
/*Line 25*/ int max(int num1, int num2, int num3) {
/* local variable declaration */
int result;
if (num1 > num2)
result = num1;
else
result = num3;
return result;
}
I get the error(s):
Expected an Identifier: Line(s) 6,25
Expected a ";": Line(s) 25
Intellisense highlights those lines and wont let me run the code. Yet in Codeblocks (Using the default GNU GCC compiler, from mingW) this EXACT code compiles just fine. What is causing this?
Multiple sources have told me that its not due to Codeblocks using GCC compiler
and Visual Studio using "cl" compiler by default.
The same sources have told me that it is also not due to the possibility of each IDE compiling the code using different C standards.
I have named the the file extension as ".c" and I get these errors
If I try to compile the code as c++(or as a ".c++" file it works, but that's not what I want.
I want C.
I would prefer to use Visual Studio over Codeblocks due to its sleek look and menu layout. I also prefer the Visual Studio debugger.
What steps can I take to successfully compile this simple code on Visual Studio 2017?
Microsoft has a notoriously defined max macro. If the macro definition is pulled into your source for whatever reason, token substitution will wreak havoc. The result of that I'd wager is what you are seeing. Mostly because by your own admission, it happens only in Visual Studio.
The solution (and test for it) is fairly simple. One of these should "fix" your code:
Rename max to something else, like my_max.
Before including any headers, add #define NOMINMAX to suppress the definition of the macros in any included MS headers.
Beyond that you are gonna have to tinker with your project settings and see what may be improperly set. This is not a macro that should be automatically added in a simple console project.
I've tried compiling this with Visual Studio 2012 RC and Intel C++ Compiler XE 12.1. I'd appreciate if you tried with some other compiler. See my comments in the code to really appreciate the weirdness of this bug. Does anyone know what's going on, and where should I file a bug report about this?
// File: NamedSameA.h
#pragma once
// File: NamedSameA.cpp
#include <vector>
#include "NamedSameA.h"
struct NamedSame // Rename this class to something else to make the program work
{
std::vector<int> data;
// Comment out the previous line or change
// the data type to int to make the program work
};
static NamedSame g_data; // Comment out this line to make the program work
// File: NamedSameB.h
#pragma once
void test();
// File: NamedSameB.cpp
#include <vector>
#include "NamedSameA.h"
#include "NamedSameB.h"
struct NamedSame
{
int data1; // Comment out this line to make the program work
std::vector<int> data2;
};
void test()
{
NamedSame namedSame;
namedSame.data2.assign(100, 42);
// The previous line produces the following runtime error:
// -------------------------------------------------------
// Debug Assertion Failed!
// Program: C:\Windows\system32\MSVCP110D.dll
// File: c:\program files (x86)\microsoft visual studio 11.0\vc\include\vector
// Line: 240
// Expression: vector iterators incompatible
}
By giving the same name to two different classes/structures you've violated the One Definition Rule. This results in undefined behavior, so any result is possible - including a crash.
I've found over the years that the more convinced I am that I've found a compiler bug, the more likely it is that my program has a fundamental flaw.
Here is the sample code that I ran on Visual Studio 2010:
#include <iostream>
int main()
{
int **p(NULL);
}
I get this error: error C2059: syntax error : 'constant'
But if I change int **p(NULL); to int **p = NULL; the above code compiles fine.
Checked this on GCC(Version:4.4.2) and both work fine. What am I missing here?
VC++ compiler seems confused about initializations of pointer to pointer ...
This works for example
int (**p)(NULL);
These don't
int *i;
int **p(&i);
int **o(NULL);
This works though
int (**p)(&i);
typedef int* intp;
intp *o(NULL);
etc... the pattern is initialization fails whenever two ** are present! I'd guess a bug! Someone from MSVC team might be able to confirm
That is either a bug in the compiler itself, or possibly you've done something and asked something else.
MSVC10 support few features from C++11, such as the following:
int **p1 = nullptr;
int **p2{}; //initialized to nullptr!
You can try any of these. Both are fine.
Looks like, defect with Visual studio, It works if i use c++ to compile # http://codepad.org/ and run the following code
int main()
{
int **p(NULL);
return 0;
}
Same works using g++ compiler as well.
You get a syntax error: apparently NULL is not defined. You should include cstdlib.