Using "safe" versions of stdio calls in MSVC and remaining cross platform? - visual-c++

I'm porting my simple Unix C code to windows using MSVC and have come across the warning C4996, "this function may be unsafe". The explanation is clear, and I can turn off the warning in the VS preferences, but I think it's worth exploring a conversion.
An example is sprintf, which it suggests replacing with sprintf_s. That causes an error on the macOS side, and I assume Linux (missing symbol). There's only perhaps 50 of these in total, so I could just #ifdef them all, but the result is ugly and I do prefer clean code.
I'm a C noob, and I'm wondering if I'm simply missing some simple solution to this, perhaps using the preprocessor? You can't simply #define it (tried that) because then both sides complain about redefined symbols, but that's about the extent of my preprocessor knowledge.

Related

Differences between GNU C++ 4.8.1 (MinGW) and Visual C++ 2013

I know question like this have been asked before, but there isn't the exact answer I'm searching for.
Today I was writing ACM-ICPC contest with my team. Usually we are using GNU C++ 4.8.1 compilator (which was available on contest). We had written code, which had time limit exceeded on test case 10. At the end of contest, less then 2 minutes remaining, I sent the exactly same submission with Visual C++ 2013 (same source file, different language) it got accepted and worked. There were more than 60 test cases and our code passed them all.
Once more I say that there were no differences between the source codes.
Now I'm just interested why it happened.
Anyone knows what the reason is?
Without knowing the exact compiler options you used, this answer might be a bit difficult to answer. Usually, compilers come with many options and provide some default values which are used as long as the user does not override them. This is also true for code optimization options. Both mentioned compilers are capable to significantly improve the speed of the generated binary when being told so. A wild guess would be that in our case, the optimization settings used by the GNU compiler did not improve the executable performance so much but the VC++ settings did. For example because not any flags were used in one case. Another wild guess would be that one compiler was generating a debug binary and the other did not (check for the option -g with GCC which switches debug symbol generation on).
On the other hand, depending on the program you created, it could of course be that VC++ was simply better in performing the optimization than g++.
If you are interested in easy increasing the performance, have a look at the high-level optimization flags at https://gcc.gnu.org/onlinedocs/gnat_ugn/Optimization-Levels.html or for the full story, at the complete list at https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html.
More input on comparing compilers:
http://willus.com/ccomp_benchmark2.shtml?p1
http://news.dice.com/2013/11/26/speed-test-2-comparing-c-compilers-on-windows

GNU g++ inline assembly block like Apple g++/Visual C++?

I am currently following a course at my University in which, at this stage, we learn about the assembler code behind certain C/C++ constructs.
The workflow usually goes like this: the lab assistant briefly speaks about a topic, we figure out the quirks and then solve some totally random problem using inline assembly.
(For example: He briefly talks about how struct (members) are stored in memory, we figure out the pattern and then we write the solution using inline assembly to a simple problem in which we use a struct.)
The lab assistant (as well as the rest of the group) is using the Visual C++ compiler and debugger (for disassembly) for his demonstrations however I cannot use it due to ethical reasons and thus I opted for g++ and gdb.
What I find awkward about g++'s inline assembly compared to Visual C++ is the fact that:
If I want to write a 'block' of inline assembly I have two options: Have a single asm("..") construct in which each instruction is preceded by a \n\t (leads to a lot of clutter). Or have each instruction in its own asm("..") block (leads to a lot of typing).
If I want to reference a local variable in the inline assembly I have to either use the extended syntax or reference it by using offsets to esp/ebp.
In respect to the two issues above I prefer the Visual C++'s inline assembly style in which in order to write an asm block all I have to do is __asm { .. } and write each instruction on a new line and in order to reference a variable I just have to write its name.
Throughout my searches I have discovered that Apple's g++ supports the same syntax as Visual C++ with a switch (-fasm-blocks) however this does not seem to be the case for GNU g++.
In the hopes that I might have missed something I am asking here if it is possible to compile Visual C++ like inline assembly blocks under GNU g++.
The syntax you are referring to is not Microsoft specific. As you have found, Apple had it too (although Apple gave up on GCC and switched to Clang). AFAIK, Metrowerks supports the same syntax. GCC does not support it (probably because GCC guys believe that GCC is so good that nobody needs to write assembly anymore :-)). However, there is no need to type \n\t all the time, you can replace it with ;. For example:
void foo()
{
asm("xor %eax,%eax;"
"rep; nop;"
"nop;"
"sfence;"
"nop;");
}
Hope it helps. Good Luck!

compiling visual C++ code in linux?

i have a visual C++ program which performs image matching. I am using openCV. I am looking to run the exe on a linux server. But i dont know how to compile visual C++ code in linux?
Can anyone plz help me in this regard . . .
If you did things smartly while writing the C++ code in MSVC, you isolated all platform-dependent code (i.e., Microsoft extensions to C++ and uses of Windows-only libraries) from the rest right from the start, and know exactly where to do the modifications to make it run on Linux as well.
Unfortunately, your question hints at this being your first attempt at cross-platform coding, and in that case, you probably littered Microsoft-isms all over your code, and have to pick through them one by one. Start the compiler, have a look at its error messages, and go from there. Good luck, it will be a pain, but also a very valuable lesson for your next project.
(I'm not finger-pointing at MSVC here. The very same is true for people who litter their code with GNU-isms and then want to have it compile on MSVC...)
The usual construct looks like this:
#if defined( _MSC_VER )
// Microsoft version
#elif defined( __GNUC__ )
// GCC version
#else
#error Platform / compiler not supported.
#endif
Edit: In case it is not obvious, the idea is to keep the ifdef'ed code above at an absolute minimum. Use typedef's, forwarding functions (i.e., log() to use either Unix or Windows logging), or - if all else fails - macros. Don't use the above all over the code, isolate it in a few header / implementation files, kept in a separate source folder.
You will also want to familiarize yourself with Makefiles (shameless plug: Makefile tutorial) or CMake, because MSVC project files don't work on Linux (obviously).
There's also winelib and stuff. Point your build system to using winegcc/wineg++ as your compiler, and go for it. It can compile a fairly large subset of windows programs. This should be a good option if all you need is to get one or two programs to work.

LLVM and visual studio .obj binary incompatibility

Does anyone know if LLVM binary compatibility is planned for visual studio combiled .obj and static .lib files?
Right now I can only link LLVM made .obj files with dynamic libs that loads a DLL at runtime (compiled from visual studio).
While there probably is very small chances that binary compatibility will happen between the two compilers, does anybody know why it is so difficult achieving this between compilers for one platform?
As Neil already said, the compatibility includes stuff like calling convention, name mangling, etc. Though these two are the smallest possible problems. LLVM already knows about all windows-specific calling conventions (stdcall, fastcall, thiscall), this is why you can call stuff from .dll's.
If we speak about C++ code then the main problem is C++ ABI: vtable layout, rtti implementation, etc. clang follows Itanium C++ ABI (which gcc use, for example, among others), VCPP - doesn't and all these are undocumented, unfortunately. There is some work going in clang in this direction, so stuff might start to work apparently. Note that most probably some parts will never be covered, e.g. seh-based exception handling on win32, because it's patented.
Linking with pure C code worked for ages, so, you might workaround these C++ ABI-related issues via C stubs / wrappers.
Apart from anything else, such as calling conventions, register usage etc, for C++ code to binary compatible the two compilers must use the same name-mangling scheme. These schemes are proprietory (so MS does not release the details if its scheme) and are in any case in a constant state of flux.

What features of C++ are not compatible with compilers other than Visual Studio?

I was told to avoid using features of C++ like these as it makes it difficult to port the code to other compilers.
The example I was given was using #ifdef instead of #pragma once in my header files.
Well, this is challenging to answer, because each compiler is different - and, more specifically, #pragma statements are not a feature of C++. #pragma means, by definition "a command to send to the compiler":
"Pragmas are machine- or operating system-specific by definition, and are usually different for every compiler." MSDN
so, essentially, whenever you see #pragma, it means "what follows next is not part of the language standard, and so may be different for every platform you target/compile on"
Those are not "C++ features", they are non-standard "extensions", non-standard functions, and "compiler features" provided by compiler developer.
short and incomplete list of microsoft-specific features that will cause trouble during porting:
pragma once. (and pretty much every pragma) Will be ignored by another compiler, which will result in multiple header inclusions. Can cause trouble.
__int32 and similar types (microsoft specific)
Everything that comes from windows.h - DWORD/WORD/HANDLE/TCHAR. Also os-specific API and system calls. This includes WinMain().
every builtin type, macros and keyword that starts with two underscores (____FUNCTION____, __int32, __declspec, etc).
Certain versionf of *printf functions - swprintf, vswprintf, etc. Some format (%S) specifications behave differently on different compilers.
*_s functions (strcpy_s, etc).
Here's a list of nonstandard behaviour in VC++: http://msdn.microsoft.com/en-us/library/x84h5b78%28VS.71%29.aspx
The very clean, but non-portable for each, in statement: Visual c++ "for each" portability

Resources