C++ - check if safe functions are needed - c

When I am using Visual Studio (MSVC), and using the strcat function, I get the error
error C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
If I was to make a project which was for compilers like GCC aswell, is there a way of detecting if these safe functions are needed, for example MSVC macro?

You can use conditional compilation for cross-platform code. Such as:
#ifdef WIN
strcat_s(...
#else
strcat(...
#endif
MSVC compiler detects such calls of the functions that were acknowledged as deprecated and generates warning C4996 on level 3. So, just compile with this level (or more) and look at warnings.

Usually I use #ifdef _CRT_INSECURE_DEPRECATE for this. It's the macro used by Visual to add these warnings in the first place, so if you're compiling on a version of Visual that gives warnings, it will be defined.

Related

`__noinline__` macro conflict between GLib and CUDA

I'm working on an application using both GLib and CUDA in C. It seems that there's a conflict when importing both glib.h and cuda_runtime.h for a .cu file.
7 months ago GLib made a change to avoid a conflict with pixman's macro. They added __ before and after the token noinline in gmacros.h: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2059
That should have worked, given that gcc claims:
You may optionally specify attribute names with __ preceding and following the name. This allows you to use them in header files without being concerned about a possible macro of the same name. For example, you may use the attribute name __noreturn__ instead of noreturn.
However, CUDA does use __ in its macros, and __noinline__ is one of them. They acknowledge the possible conflict, and add some compiler checks to ensure it won't conflict in regular c files, but it seems that in .cu files it still applies:
#if defined(__CUDACC__) || defined(__CUDA_ARCH__) || defined(__CUDA_LIBDEVICE__)
/* gcc allows users to define attributes with underscores,
e.g., __attribute__((__noinline__)).
Consider a non-CUDA source file (e.g. .cpp) that has the
above attribute specification, and includes this header file. In that case,
defining __noinline__ as below would cause a gcc compilation error.
Hence, only define __noinline__ when the code is being processed
by a CUDA compiler component.
*/
#define __noinline__ \
__attribute__((noinline))
I'm pretty new to CUDA development, and this is clearly a possible issue that they and gcc are aware of, so am I just missing a compiler flag or something? Or is this a genuine conflict that GLib would be left to solve?
Environment: glib 2.70.2, cuda 10.2.89, gcc 9.4.0
Edit: I've raised a GLib issue here
It might not be GLib's fault, but given the difference of opinion in the answers so far, I'll leave it to the devs there to decide whether to raise it with NVidia or not.
I've used nemequ's workaround for now and it compiles without complaint.
GCC's documentation states:
You may optionally specify attribute names with __ preceding and following the name. This allows you to use them in header files without being concerned about a possible macro of the same name. For example, you may use the attribute name __noreturn__ instead of noreturn.
Now, that's only assuming you avoid double-underscored names the compiler and library use; and they may use such names. So, if you're using NVCC - NVIDIA could declare "we use noinline and you can't use it".
... and indeed, this is basically the case: The macro is protected as follows:
#if defined(__CUDACC__) || defined(__CUDA_ARCH__) || defined(__CUDA_LIBDEVICE__)
#define __noinline__ __attribute__((noinline))
#endif /* __CUDACC__ || __CUDA_ARCH__ || __CUDA_LIBDEVICE__ */
__CUDA_ARCH__ - only defined for device-side code, where NVCC is the compiler (ignoring clang CUDA support here).
__CUDA_LIBDEVICE__ - Don't know where this is used, but you're certainly not building it, so you don't care about that.
__CUDACC__ defined when NVCC is compiling the code.
So in regular host-side code, including this header will not conflict with Glib's definitions.
Bottom line: NVIDIA is (basically) doing the right thing here and it shouldn't be a real problem.
GLib is clearly in the right here. They check for __GNUC__ (which is what compilers use to indicate compatibility with GNU C, AKA the GNU extensions to C and C++) prior to using __noinline__ exactly as the GNU documentation indicates it should be used: __attribute__((__noinline__)).
GNU C is clearly doing the right thing here, too. Compilers offering the GNU extensions (including GCC, clang, and many many others) are, well, compilers, so they are allowed to use the double-underscore prefixed identifiers. In fact, that's the whole idea behind them; it's a way for compilers to provide extensions without having to worry about conflicts to user code (which is not allowed to declare double-underscore prefixed identifiers).
At first glance, NVidia seems to be doing the right thing, too, but they're not. Assuming you consider them to be the compiler (which I think is correct), they are allowed to define double-underscore prefixed macros such as __noinline__. However, the problem is that NVidia also defines __GNUC__ (quite intentionally since they want to advertise support for GNU extensions), then proceeds to define __noinline__ in an incompatible way, breaking an API provided by GNU C.
Bottom line: NVidia is in the wrong here.
As for what to do about it, well that's a less interesting question but there are a few options. You could (and should) file an issue with NVidia to fix their compiler. In my experience they're pretty good about responding quickly but unlikely to get around to fixing the problem in a reasonable amount of time.
You could also send a patch to GLib to work around the problem by doing something like
#if defined(__CUDACC__)
__attribute__((noinline))
#elif defined(__GNUC__)
__attribute__((__noinline__))
#else
...
#endif
If you're in control of the code which includes glib, another option would be to do something like
#undef __noinline__
#include glib_or_file_which_includes_glib
#define __noinline__ __attribute__((noinline))
My advice would be to do all three, but especially the first one (file an issue with NVidia) and find a way to work around it in your code until NVidia fixes the problem.

How to see (or check) values of macro function in C during debugging mode in MS visual studio?

I would like to check a numerical value evaluated by a function macro in C during debugging mode. I defined a function as macro like below.
#define H_H2(T) 0.2584e4*exp(170/(T))
When I tried to evaluate this function H_H2(298) during debugging mode at watch window in Visual studio, it generated an error identifier "H_H2" is undefined.
Could someone let me know how to evaluate a macro function during debugging mode ?
You can't. Macros are resolved during the preprocessor, and as a result they don't exist in compiled code.
If you need to debug such an expression, create a function, or step through the disassembled code (Ctrl+,G in VS2019).
It is not possible in the VisualStudio if you use Microsft debugger. But you can debug it if you use gdb and gcc compiler. It is possible if you debug WSL application in the VS https://learn.microsoft.com/en-us/cpp/linux/deploy-run-and-debug-your-linux-project?view=msvc-160.
When you compiler using gcc family debuggers and use gdb you can easily see and evaluate macro definitions by adding the -g3 compiler option.
From gcc documentation:
Level 3 includes extra information, such as all the macro definitions
present in the program. Some debuggers support macro expansion when
you use -g3.

How to disable the warning about using deprecated gets in GCC?

I'm running a CTF and I am currently writing a problem that exploits C's gets function. I understand that the function is deprecated and dangerous and I would never use it in any other circumstance. Unfortunately, gcc compiles my code and when I run the binary when the gets function is hit, I get a friendly error message:
warning: this program uses gets(), which is unsafe.
This would normally be great, because it warns you that gets is unsafe, but unfortunately, in my CTF, I think that this error message makes the problem a bit too easy. Do you know how I would go about disabling this warning? Thanks!
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Note: I just realized that your question title seems to be misplaced - The warning you got is from macOS about executing a program which uses gets(). It has nothing to do with the compilation by using GCC.
:-/ Any way, I let my answer alive for reference.
Just as comment: I googled a bit about what you are looking for, but there seems to be no reliable way to disable this warning when executing the program. One suggested rebuilding /usr/lib/libSystem.B.dylib without any result or experience if it indeed works, but I personally think this a bit too extreme and even can be harmful. - I do not recommend this technique.
If you really want to create an exploit program, try to rebuild gets() by a costum-made function and name the function a bit different, like f.e. gets_c(). This should be a workaround to disable this warning from macOS.
Old answer (regarding GCC itself):
First of all, you seem to be using a C99 or C89/C90-compliant compiler or alternatively compile with std=c99 or std=c89/std=c90 option, because only compilers conform to standards preceding C11 warn about gets() being deprecated.
ISO/IEC removed the gets() function in C11. If you would compile with a C11 or newer standard-compliant compiler, you would get an error about the implicit declaration of gets() when using it in the code instead:
"error: implicit declaration of function 'gets'; did you mean 'fgets'? [-Werror=implicit-function-declaration]"
If you want to suppress the warning at compilation, use the -Wno-deprecated-declarations option at compiling to disable the diagnostic for deprecated declarations.
From the GCC online docs:
-Wno-deprecated-declarations
Do not warn about uses of functions, variables, and types marked as deprecated by using the deprecated attribute. (see Function Attributes, see Variable Attributes, see Type Attributes.)
Source: https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Warning-Options.html
If you want to embed the suppression of the warning in your code use the approach used in DavidĀ“s deleted answer implementing a suppression for -Wno-deprecated-declarations by using #pragma:
char str[256];
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
gets(str);
#pragma GCC diagnostic pop

identifier "snprintf" is undefined

I am trying to compile a console C application on HP-UX machine using the aCC compiler [HP C/aC++ B3910B A.06.26].The compilation always failing with the below error :
******"Common/Common.c", line 153: error #2020: identifier "snprintf" is undefined
snprintf( BufferMessage, MSG_SIZE,
^
1 error detected in the compilation of "Common/Common.c".
gmake: *****[Common/Common.o] Error 2********
However the Common.C file include already the library which contain normally the method snprintf.
any idea to solve this isse plz?
Thanks in advance for all
snprintf() was introduced in C99, and is defined in <stdio.h>, so your compiler must support that version of the C standard. If it does not support C99 then use sprintf() instead.
Version 6 of the HPUX C compiler is C99-compliant but you may need switches to enable it.
The 6.20 release notes stated that the next release should switch the default mode from C89 to C90, and you're running 6.26. It appears that it did happen in 6.25, which was the release following 6.20.
You could force C99 mode by using cc -AC99 (or cc -Ae now that C99 is the default) to see if that helps. It may be that, even though the default C compilation mode is C99, you still have to specify it's C rather than C++.
Some other things to check:
See if you've included the stdio.h header.
See if you get a similar problem with just printf, which is also in that header.
Run the compiler generating pre-processor output (cc -E) and check that it's defined somewhere.

Is there any good reason not to use 'define' with variable argument length?

Recently I came upon this code:
#define LOG(type, str) printf(str)
#define LOG1(type, str,arg1) printf(str,arg1)
#define LOG2(type, str,arg1,arg2) printf(str,arg1,arg2)
#define LOG3(type, str,arg1,arg2,arg3) printf(str,arg1,arg2,arg3)
#define LOG4(type, str,arg1,arg2,arg3,arg4) printf(str,arg1,arg2,arg3,arg4)
The code was written recently. So I guess it can be compiled with C99.
My question is: Why not use a simple macro with variable arguments length? We would just limit ourselves to LOG macro and nothing more. Not to mention that we won't have to add LOG5, LOG6, etc. Would something terrible happen if we get a stack trace, run out of memory, anything that would make this solution useful?
I am a minimalist, if we can get fewer lines the better. But am I missing something here? Was this intentional or it is a bad coding practice?
Preprocessor support for variadic macros looks to me the only good reason. We had for decades in our project LOG, LOG1 etc, but did upgrade to ... recently.
As per wikipedia:
Several compilers support variable-argument macros when compiling C and C++ code: the GNU Compiler Collection 3.0,[2] Visual Studio 2005,[3] C++Builder 2006, and Oracle Solaris Studio (formerly Sun Studio) Forte Developer 6 update 2 (C++ version 5.3).[5] GCC also supports such macros when compiling Objective-C.
If you know your platform, then use fancy variadic macros. If there are few to support, then things could turn out to be more interesting

Resources