I'm using C++11's static_assert to perform compile-time checks to prevent the use of insecure functions, and/or to provide feedback to the user when a new feature should be used and the relevant APIs are out of date (e.g. using std::strftime, std::to_string, etc.).
I want to force failure if any source code attempts to use outdated functions, but I need it to be totally cross-platform, and also bypass or workaround other 'helpers' such as Microsofts own deprecations.
I see I can use .sections when working with a gnu toolchain, which I can see the definition for in OpenBSD's cdefs.h (http://ninjalj.blogspot.co.uk/2011/11/your-own-linker-warnings-using-gnu.html) but I have nothing equivalent for Visual Studio.
For example, I can use the following code without a problem to prevent strcpy/strcat:
# define COMPILE_TIME_CHECK(expression, message) static_assert(expression, message)
# define GUARANTEE_FAILURE (0 == 1)
# define DISABLED_FUNCTIONS_MESSAGE_CSTRING "strcpy, strcat must be replaced with strlcpy and strlcat, respectively"
# define strcat COMPILE_TIME_CHECK(GUARANTEE_FAILURE, DISABLED_FUNCTIONS_MESSAGE_CSTRING);
it may be unclean but works; but the trouble is when attempting to do the same with others that don't play as nicely, such as ctime and localtime:
_CRT_INSECURE_DEPRECATE(localtime_s) static __inline struct tm * __CRTDECL localtime(const time_t * _Time)
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\time.inl(86): error C2059: syntax error : 'static_assert'
Is there a way I can block specific functions (warning or compile failure), while providing a message for what to use in their place, without conflict from gcc/visual studio in a suitable way? The CRT macros in visual studio do not prevent the above error with the aforementioned defines.
I'm not convinced something like __declspec(deprecated) int strcpy(char*,char*); (as noted here: C++ mark as deprecated) is going to always play ball, and is a lot more work & less descriptive than just setting a define for the function name.
you can use Disable:warning {#warning Code}
Related
I found that documentation on MSVC's _doserrno global variable is very "sparse", so to say. Its existence is mentioned in the documentation for errno, the Standard C global variable for error codes. At the same time _doserrno seems to be an MSVC extension. The documentation mentions that it may provide additional information on I/O errors, but it also says most functions do not set it.
But what functions do set it? There doesn't seem to be a list for this, or did I miss anything? In the documentation for individual functions I also do not see any mention like "this function does [not] set _doserrno". So how do I know whether a function does set it or not? Very confusing, isn't it?
Furthermore, the documentation doesn't say a word about how the values of _doserrno have to be interpreted. If figured, from my own testing, that it's just the Win32 Error Code passed through from the Win32 API to the C API. But is this always the case? And how to convert _doserrno to string?
(I know I could use FormatMessage() directly from Win32 API to get a string from Win32 Error Codes. But reverting to the Win32 API totally contradicts the purose of having _doserrno in the C API!)
Regards,MuldeR
I think it’s impossible to do what you want.
If you want to stick to portable C functions for IO, you won’t get sensible error codes or messages: neither C nor C++ standard library expose that stuff.
And if you want good error messages on Windows, you have to use Win32 API instead of portable C functions. BTW, there’re good OO wrappers above that, e.g. see CAtlFile for files.
Just for completeness since I just looked into this:
Look at the mapping in
C:\Program Files (x86)\Windows Kits\10\Source<SDKver>\ucrt\misc\errno.cpp
struct errentry
{
unsigned long oscode; // OS return value
int errnocode; // System V error code
};
These are the only mappings used between CRT error codes and OS error codes. Not all CRT error codes are mapped and just a fraction of the OS error codes. To get more detail and probably the real error you need to use the Windows SDK.
I am trying for two weeks to create a DLL to which I can pass strings and get back strings. But still no success.
I tried this on Dev-C++(TDM-GCC 4.9.2) and visual studio community 2015. I searched a lot about this and tried almost every sample code I found but I have no success.
I have to use this DLL with MetaTrader Terminal 4.
Here is a one sample code, which I used. This code compiles successfully but when I send a string to this, from MT4, I get an access violation error.
#ifndef MYLIB_HPP
#define MYLIB_HPP
#include <string>
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllimport)
#else
#define MYLIB_API __declspec(dllexport)
#endif
bool MYLIB_API test(const std::string& str);
#endif
bool MYLIB_API MyTest(const std::string& str)
{
return (str == "Hi There");
}
If you do share a C++ string between a DLL and another executable, both need to have been compiled with the same tool-chain. This is because std::string is defined in header only. So, if the DLL and executable use different string headers, they may well be binary incompatible.
If you want to make sure that things do work with different tool-chains, stick to NULL terminated C strings.
You have just experienced one of the MQL4 tricks,the MQL4 string is not a string but a struct thus #import on MQL4 side will make MT4 to inject that, not matching your DLL C-side expectations and the access-violation error is straightforward, as your C-side code tried to access the MQL4 territories...
First rule to design API/DLL: READ the documentation very carefully.
Yes, one may object, that the MQL4 doc is somewhat tricky to follow, but thus more double the Rule#1, read the documentation very, very, very carefully as some important design facts are noted almost hidden in some not very predictable chapters or somewhere in explanations of ENUM tables, compiler directives, pragma-s side-notes et al.
Second rule: design API/DLL interface so as to allow smooth integration
MQL4 has changed the rules somewhere about Build 670+. Good news is, the MetaQuotes has announced, that there will be no further investment on their side into MT4 further developlments, so the MT4-side of the DLL/API integration will hopefully stop from further creeping.
Given your statement, that you design the DLL/API, try to design future-proof specification -- use block of uchar[]-s instead of "interpretations"-sensitive string, pass both inputs and outputs by-reference and return just some form of int aReturnCODE = myDLL_FUNC( byRefParA, byRefParB, byRefRESULT ); and your efforts will result in clean code, better portability among 3rd party language-wrappers and will also minimise your further maintenance costs.
Most likely, your code and the one you're linking against have been compiled with a different ABI for std::string, i.e. the string used by the library has a different memory layout (and sizeof) than the one you're compiling with.
I once ran into this problem when linking against the hdf5 library and using gcc. In this case, the problem could be solved by reverting to a previous ABI, as explained here.
However, the problem also occurred with clang, when such a solution was not available. Thus, to make this all working I had to avoid using std::string in any calls to the library (hdf5 in my case) that was compiled with the different ABI, and instead make do with the hdf5 interface using const char*.
I have been writing Java for a long time using Eclipse, now trying to switch to C++ in Visual Studio. From Eclipse/Java I know such auto-complete features: I write
bar = Foo.valueOf(x);
bar.doSomething(y, z);
and Eclipse offers me both to import whatever Foo I might mean, and declare bar as local variable, field, or parameter. Or create the function doSomething() with the appropriate signature, auto-adding missing imports to Foo. I am missing a corresponding feature on Visual Studio 2015, which does for example
add the corresponding #include and #pragma comment(lib, statements,
add these statements in a clear order, so that they work as expected (something like organize imports),
add namespace statements
declare variables, fields, and parameters on click/keypress
create function bodies, adding the corresponding foreward declarations to the respective header files, adding missing includes required by the declaration
…
The only things that I found so far is the “add class” dialog. When writing an unknown function name, right clicking and choosing “quick actions and refactorings” → Create declaration / definition, a window opens with the text
int main(int argc, char * argv[]);
but it does not create a definition for that function.
Are there some better “save me typing work” functions available in Visual Studio 15, and if yes, how can I benefit from them? Is there another way I could go, such as writing the C++ program (Windows API) in an other IDE (are there any for Winapi C++ which do better?)
Resharper by JetBrains does what you are asking for more or less. It will notice an error in your code, whether it being that something wasn't fully initialized, or something that you needed to include, or a host of other things.
It is not free though, but you can try it on a 30 day trial.
I don't know of an IDE that supports winapi functions like you're asking though. I think you'll just have to pick your favorite IDE and get used to it.
I have recently been given a sizeable chunk of legacy C++ code which I want to move to the latest VS2012 compiler or the GCC compiler.
When I look at some of the files however, I can see some items of code prefixed with a $ sign.
For example I have some include lines:
#include "utlString.h"
$include "gclFloat_c.h"
and an enum declaration:
$enum gclEFormatType
{
StandardFormat = 0, // e.g. 192784.272674700000000000
ScientificFormat = 1, // e.g. 1.927842726747E5 (includes exponent)
ExtendedFormat = 2 // e.g. 1.927842726747E5S30 (includes exponent and significant digit count)
};
and I have some other declarations:
$cointerface [dual] gclIFloat : IDispatch
{
...
}
$coclass [STA] gclCFloat;
I think they may be pre-processor macros, but I'm not sure. Can anyone tell me what there are and how are they used?
Thanks
There are three possibilities:
The code is run through some external preprocessor before being fed to the compiler;
It's some compiler-specific extension (check your compiler's documentation); or
It's a syntax error.
Looks like those files are intended to be parsed to generate include files for both c++ and a scripting wrapper, like swig, but the [dual] and [sta] make me think it's targeting C# as the second language.
It's likely to be Visual Studio nmake syntax.
You can find many tutorial about this on the internet, the dollar sign is also used as an identifier for tokens with a Visual Studio specific syntax ( outside nmake ).
We have a fairly large C++ project which I am now in the process of moving to VS2010 and also updating a few libs along the way. So far everything builds just fine now, except I get (to me) quite weird errors where apparently a number of (edit: non-)standard C functions and symbols are not defined:
error C2039: 'strdup' : is not a member of '`global namespace'' ...\ACE_wrappers\ace\OS_NS_string.inl 222
...
error C2065: 'O_WRONLY' : undeclared identifier ...\ACE_wrappers\ace\OS_NS_unistd.inl 1057
...
This affects the following functions and symbols for me:
strdup getcwd O_WRONLY
putenv swab O_TRUNC
access unlink S_IFDIR
chdir mkdir S_IFREG
rmdir tempnam O_RDONLY
isascii
One part in the include file from ACE I experimented with was the strdup part which looks like this:
ACE_INLINE char *
ACE_OS::strdup (const char *s)
{
# if (defined (ACE_LACKS_STRDUP) && !defined(ACE_STRDUP_EQUIVALENT)) \
|| defined (ACE_HAS_STRDUP_EMULATION)
return ACE_OS::strdup_emulation (s);
# elif defined (ACE_STRDUP_EQUIVALENT)
return ACE_STRDUP_EQUIVALENT (s);
# elif defined (ACE_HAS_NONCONST_STRDUP)
return ::strdup (const_cast<char *> (s));
#else
return ::strdup (s);
# endif /* (ACE_LACKS_STRDUP && !ACE_STRDUP_EQUIVALENT) || ... */
}
There are loads of similar sections for other functions above and below, all of which compile just fine.
The path taken in my case is the last one, i.e. return ::strdup (s);. If I hit F12 on the ::strdup VS takes me to the declaration in string.h of the C standard library.
If I remove the namespace qualifier it builds, although IntelliSense tells me that it's now a recursive call so it probably won't work. If I change the namespace to std:: I get around 270 more errors, this time from several other projects. If I change the function to ::_strdup it builds. Including string.h as the very frst thing changes nothing.
(Nota bene: “it builds” refers to “this particular compiler error disappears at that location, but it still leaves the errors about the other functions, obviously.)
I'm a little at a loss here. I noticed that many larger libraries either build their own abstraction over the standard library or provide things that are not there by default and that was a point where ACE and ImageMagick already clashed (in both typedefing ssize_t but with incompatible definitions). Since we pull in quite a few libraries (I don't have an exact overview either, right now) this could well be another clash, caused by the wrong include order and similar things. This is also hinted at by the fact that the same includes from ACE apparantly work fine in other projects in the same solution.
Anyone have an idea what I could look for here at least? The build log with /showIncludes is just 24k lines so I don't exactly see many patterns there, except that string.h gets included way before the problematic ACE header.
And I wouldn't want to modify the library source code as that will only bite us again if we update to a newer version.
"a number of standard C functions and symbols are not defined"
strdup is not a standard C function. It is defined in POSIX, but not in C or C++. Quoting MSDN:
These POSIX functions are deprecated beginning in Visual C++ 2005. Use the ISO C++ conformant _strdup, _wcsdup, _mbsdup instead.
It appears to me that none of the symbols you list are standard C functions.
With Mark B's comment which prompted me to look at 12 MiB of Preprocessor output I was able to solve it. In string.h the snippet where strdup is defined looks like this:
#if !__STDC__
...
_Check_return_ _CRT_NONSTDC_DEPRECATE(_strdup) _CRTIMP char * __cdecl strdup(_In_opt_z_ const char * _Src);
It so happened that this single project defines the __STDC__ symbol which causes a lot of non-standard-C-but-still-in-the-C-standard-library (thanks, Robφ for nitpicking but not solving the issue) functions to disappear completely.
I know they're deprecated, I got plenty of warnings that tell me so. But as noted, I'm not maintaining project-specific patches to 3rd-party libraries we use just to have the same fun all over again if we ever update them.
If I understand VS correctly, the strdup, etc. function names are deprecated nowadays (not POSIX compliant, I think). You should use the underlined versions.
When this happened for me, I ran a global search and replace, since it seemed like a sensible thing to do and keeps the source code in good condition for the future (VS 2012 is already out! :) ).