Deprecated conversion from string constant to 'char *' in CUDA allocation template function - c++

I have made some helper functions for doing operations with CUDA __constant__ pointers (allocation, copyToSymbol, copyFromSymbol, etc). I also have error checking in place as suggested by talonmies here. Here is a basic working example:
#include <cstdio>
#include <cuda_runtime.h>
__constant__ float* d_A;
__host__ void cudaAssert(cudaError_t code,
char* file,
int line,
bool abort=true) {
if (code != cudaSuccess) {
fprintf(stderr, "CUDA Error: %s in %s at line %d\n",
cudaGetErrorString(code), file, line);
if (abort) {
exit(code);
}
}
}
#define cudaTry(ans) { cudaAssert((ans), __FILE__, __LINE__); }
template<typename T>
void allocateCudaConstant(T* &d_ptr,
size_t size) {
size_t memsize = size * sizeof(T);
void* ptr;
cudaTry(cudaMalloc((void**) &ptr, memsize));
cudaTry(cudaMemset(ptr, 0, memsize));
cudaTry(cudaMemcpyToSymbol(d_ptr, &ptr, sizeof(ptr),
0, cudaMemcpyHostToDevice));
}
int main() {
size_t size = 16;
allocateCudaConstant<float>(d_A, size);
return 0;
}
When I compile this with nvcc, I get the following warning:
In file included from tmpxft_0000a3e8_00000000-3_example.cudafe1.stub.c:2:
example.cu: In function ‘void allocateCudaConstant(T*&, size_t) [with T = float]’:
example.cu:35: instantiated from here
example.cu:29: warning: deprecated conversion from string constant to ‘char*’
I understand what the warning means, but I can't for the life of me figure out where it is coming from. If I don't make allocateCudaConstant a template function, I don't get the warning. If I don't wrap cudaMemcpyToSymbol in cudaTry, I also don't get the warning. I know it is just a warning, and if I compile with -Wno-write-strings I can suppress the warning. The code runs fine but I don't want to get in the habit of ignoring warnings and if I suppress the warnings, I may hide other issues that need to be addressed.
So, can anyone help me figure out where the warning is coming from and how I can suppress it?

Change char* file to const char* file in the declaration of cudaAssert. You don't need to modify the string, so you should not ask for a modifyable string.

Related

Two different results passing pointer-to-array to a function in C and C++?

I have a question regarding to the code snippet appended below. Anyway I ran the snippet on ideone.com and got two different results
C: Succeed.
C++: Error:
prog.cpp: In function ‘int main()’:
prog.cpp:20:13: error: cannot convert ‘int* (*)[2][10]’ to \
‘int* (*)[10]’ for argument ‘1’ to ‘void foo(int* (*)[10], size_t)’
foo(&a, LEN);
^
The result in C++ is what I expect, but it runs successfully in C, and it seems like it's compiler dependent because people on the chat helping ran the snippet only got a warning.
So which part I've missed? Is that C automatically did some conversion?
#include <stdio.h>
#include <stddef.h>
#define LEN 2
void foo(int* a[][10], size_t len) {
printf("%s\n", "successfully called foo.");
}
int main(void) {
// a is an LEN-array of an 10-array of (int *)
int *a[LEN][10] = {{0}};
// but the identifier `a` will decay to be a pointer of type int*[10]
// p1 is a pointer to an 10-array of (int *)
int *(*p1)[10] = 0;
foo(a, LEN);
foo(&a, LEN);
return 0;
}
Drastic edit; previous answer was wrong as pointed out in the comments.
The program is ill-formed in both C and C++. But the standards of the respective languages don't disallow successfully compiling programs that violate the imposed constraints. This allows the implementations to extend the language. Implementations are merely required to issue a diagnostic message. Both a warning and an error are conforming behaviours.
For whatever reason, the compiler that you use (through ideone) has chosen to behave differently when compiling C++.
This is not valid in C. Using gcc with -Wall -Wextra, it outputs the following:
x1.c: In function ‘main’:
x1.c:19:9: warning: passing argument 1 of ‘foo’ from incompatible pointer type [-Wincompatible-pointer-types]
foo(&a, LEN);
^
x1.c:5:6: note: expected ‘int * (*)[10]’ but argument is of type ‘int * (*)[2][10]’
void foo(int* a[][10], size_t len) {
^~~
The types are not compatible. It only shows up as a warning because C tends to allow various pointer conversions even though they aren't proper.
You can however do this:
int *(*p1)[10] = a;
foo(a, LEN);
foo(p1, LEN);

Mex file building with Octave (issue with wrappers)

I am currently porting some code from Matlab to Octave. Some of the functions of the Matlab code use the Piotr's Computer Vision Matlab Toolbox (here) that includes some mex files.
In Matlab, everything is working like a charm but when I run my codes with Octave, it throws this error:
error: 'imResampleMex' undefined near line 50 column 5
However all the internal paths within the toolbox should be good. I figured out that the way Matlab and Octave handle mex files is different and tried to build one of the mex files from the C++ function within Octave like this:
mkoctfile --mex imResampleMex.cpp
It fails and throws the following error messages related to the C++ wrappers function:
In file included from imResampleMex.cpp:6:0:
wrappers.hpp:21:24: error: 'wrCalloc' declared as an 'inline' variable
inline void* wrCalloc( size_t num, size_t size ) { return calloc(num,size);
^
wrappers.hpp:21:24: error: 'size_t' was not declared in this scope
wrappers.hpp:21:36: error: 'size_t' was not declared in this scope
inline void* wrCalloc( size_t num, size_t size ) { return calloc(num,size);
^
wrappers.hpp:21:48: error: expression list treated as compound expression in initializer [-fpermissive]
inline void* wrCalloc( size_t num, size_t size ) { return calloc(num,size);
^
wrappers.hpp:21:50: error: expected ',' or ';' before '{' token
inline void* wrCalloc( size_t num, size_t size ) { return calloc(num,size);
^
wrappers.hpp:22:24: error: 'wrMalloc' declared as an 'inline' variable
inline void* wrMalloc( size_t size ) { return malloc(size); }
^
wrappers.hpp:22:24: error: 'size_t' was not declared in this scope
wrappers.hpp:22:38: error: expected ',' or ';' before '{' token
inline void* wrMalloc( size_t size ) { return malloc(size); }
^
wrappers.hpp: In function 'void wrFree(void*)':
wrappers.hpp:23:44: error: 'free' was not declared in this scope
inline void wrFree( void * ptr ) { free(ptr); }
^
wrappers.hpp: At global scope:
wrappers.hpp:28:17: error: 'size_t' was not declared in this scope
void* alMalloc( size_t size, int alignment ) {
^
wrappers.hpp:28:30: error: expected primary-expression before 'int'
void* alMalloc( size_t size, int alignment ) {
^
wrappers.hpp:28:44: error: expression list treated as compound expression in initializer [-fpermissive]
void* alMalloc( size_t size, int alignment ) {
^
wrappers.hpp:28:46: error: expected ',' or ';' before '{' token
void* alMalloc( size_t size, int alignment ) {
^
imResampleMex.cpp: In function 'void resampleCoef(int, int, int&, int*&, int*&, T*&, int*, int)':
imResampleMex.cpp:21:39: error: 'alMalloc' cannot be used as a function
wts = (T*)alMalloc(nMax*sizeof(T),16);
^
imResampleMex.cpp:22:43: error: 'alMalloc' cannot be used as a function
yas = (int*)alMalloc(nMax*sizeof(int),16);
^
imResampleMex.cpp:23:43: error: 'alMalloc' cannot be used as a function
ybs = (int*)alMalloc(nMax*sizeof(int),16);
^
imResampleMex.cpp: In function 'void resample(T*, T*, int, int, int, int, int, T)':
imResampleMex.cpp:48:43: error: 'alMalloc' cannot be used as a function
T *C = (T*) alMalloc((ha+4)*sizeof(T),16); for(y=ha; y<ha+4; y++) C[y]=0;
^
warning: mkoctfile: building exited with failure status
The wrappers.hpp file is looking like this:
#ifndef _WRAPPERS_HPP_
#define _WRAPPERS_HPP_
#ifdef MATLAB_MEX_FILE
// wrapper functions if compiling from Matlab
#include "mex.h"
inline void wrError(const char *errormsg) { mexErrMsgTxt(errormsg); }
inline void* wrCalloc( size_t num, size_t size ) { return mxCalloc(num,size); }
inline void* wrMalloc( size_t size ) { return mxMalloc(size); }
inline void wrFree( void * ptr ) { mxFree(ptr); }
#else
// wrapper functions if compiling from C/C++
inline void wrError(const char *errormsg) { throw errormsg; }
inline void* wrCalloc( size_t num, size_t size ) { return calloc(num,size); }
inline void* wrMalloc( size_t size ) { return malloc(size); }
inline void wrFree( void * ptr ) { free(ptr); }
#endif
// platform independent aligned memory allocation (see also alFree)
void* alMalloc( size_t size, int alignment ) {
const size_t pSize = sizeof(void*), a = alignment-1;
void *raw = wrMalloc(size + a + pSize);
void *aligned = (void*) (((size_t) raw + pSize + a) & ~a);
*(void**) ((size_t) aligned-pSize) = raw;
return aligned;
}
// platform independent alignned memory de-allocation (see also alMalloc)
void alFree(void* aligned) {
void* raw = *(void**)((char*)aligned-sizeof(void*));
wrFree(raw);
}
#endif
I imagine I need to modify this file but my knowledge of C++ and of mex files being close to non-existent, I am struggling figuring a way out of this mountain of errors. I don't even have a clue whether I'm going in the right direction or not... Any help is welcome!
Edit 1:
I modified my wrappers.hpp file adding #include <stdlib.h> to it. A mex file is now created. However, when running the function calling the file, I now get the following error:
error: failed to install .mex file function 'imResampleMex'
error: called from
imResample at line 50 column 4
Here are the steps I used to solve the issue of creating the mex files from the Piotr's Computer Vision Matlab Toolbox for Octave (concerns the cpp files of the folder channels only).
The original mex files that come with the toolbox are built for Matlab and do not work with Octave. While building them from Octave a call is made to the file wrappers.hpp.
This file has to be modified by adding these two lines at the beginning of the file: #include <stdlib.h> and #include "mex.h".
For building the mex file, in the Octave prompt type (while being in the directory of the cpp file):
mkoctfile --mex -DMATLAB_MEX_FILE the_file.cpp
This way the Octave compatible mex file is created.
Edit 23/05/2017 - After receiving more questions from people having trouble generating these files I released the generated files on Github: https://github.com/Eskapp/Piotr_vision_extrafiles_Octave. Feel free to use them.
You'll need to add them manually to the Computer Vision toolbox.

Missing an error when incorrectly passing string to printf-style log function

It is very common for any medium-to-large project to replace printf with a custom log function. Here is a minimal C++ example and its usage:
#include <stdio.h>
#include <stdarg.h>
#include <string>
void log_printf(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap); // real code obviously does something fancier
va_end(ap);
}
int main() {
std::string x = "Hello";
// correct code
printf("String is %s\n", x.c_str());
log_printf("String is %s\n", x.c_str());
// incorrect code
printf("String is %s\n", x); // bad line 1
log_printf("String is %s\n", x); // bad line 2
}
The simple logger receives a variable amount of arguments and calls vprintf to output them to standard output. The lines under 'correct code' demonstrate correct usage of this logger. My question involves the 'bad' lines, where a string object is incorrectly passed instead of a pointer to the character buffer.
Under GCC 4.6 (tested under Linux) neither of the bad lines can compile, which is a good thing because I want to catch such incorrect usage. The error is:
error: cannot pass objects of non-trivially-copyable type ‘std::string {aka struct std::basic_string<char>}’ through ‘...’
However in GCC 5.1 it has apparently become possible to pass non-trivially-copyable objects, and the compilation succeeds. If I use -Wall then only 'bad line 1' raises a warning about an unexpected argument type, but 'bad line 2' with the log_printf compiles without issue in any case. Needless to say both lines produce garbage output.
I can catch 'bad line 1' with -Wall -Werror, but what about 'bad line 2'? How can I cause it to also generate a compilation error?
For your own functions you need to use a common function attribute call format:
void log_printf(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
void log_printf(const char* fmt, ...) {
...
}
Note that the attribute must be set on a function declaration, not the definition.
The first argument to the format attribute is the style, in this case printf (scanf is also possible, for functions that works like scanf), the second argument is the format string, and the third argument is where the ellipsis ... is. It will help GCC check the format strings like for the standard printf function.
This is a GCC extension, though some other compilers have adopted it to become GCC compatible, most notably the Intel C compiler ICC and Clang (the standard compiler used on OSX and some BSD variants). The Visual Studio compiler does not have this extension, and I know of no similar thing for Visual C++.

How do I use errorno and _get_errno?

Calling system() to run an external .exe and checking error code upon errors:
#include <errno.h>
#include <stdlib.h>
function()
{
errno_t err;
if( system(tailCmd) == -1) //if there is an error get errno
{
//Error calling tail.exe
_get_errno( &err );
}
}
First two compile errors:
error C2065: 'err' : undeclared identifier
error C2065: 'errno_t' : undeclared identifier
Not sure why as I am including the required and optional header files?
Any help is appreciated. Thank You.
A typical usage is like:
if (somecall() == -1) {
int errsv = errno;
printf("somecall() failed\n");
if (errsv == ...) { ... }
}
which is taken from here.
Just use 'errno' without any declaration. It is a macro that expands to an int value.
In the world of Standard C, the type 'errno_t' is defined by TR24731-1 (see Do you use the TR 24731 'safe' functions? for more information) and you have to 'activate it' by defining '__STDC_WANT_LIB_EXT1__'.
However, you appear to be working on Windows (judging from 'tail.exe', and also the non-standard '_get_errno()'). The rules there may depend on the C compiler you are using.
You should be able to chase down the information from this MSDN article on 'Security Enhancements in the CRT'. My impression was that it should be defined unless you actively suppress the feature, so check out whether you are actively suppressing it in your compilations.
Be aware that the MSVC definition of functions such as vsnprintf_s() do not match the TR24731-1 definitions:
MSDN:
int vsnprintf_s(
char *buffer,
size_t sizeOfBuffer,
size_t count,
const char *format,
va_list argptr
);
TR 24731-1:
int vsnprintf_s(
char * restrict s,
rsize_t n,
const char * restrict format,
va_list arg
);
The difference is not just a question of type aliases or qualifiers (rsize_t, restrict) - there are two sizes in the MS version and one in the Standard version. So much for standardization!

Suppress unused variable warning in C++ => Compiler bug or code bug?

Presently, I am using the following function template to suppress unused variable warnings:
template<typename T>
void
unused(T const &) {
/* Do nothing. */
}
However, when porting to cygwin from Linux, I am now getting compiler errors on g++ 3.4.4 (On linux I am 3.4.6, so maybe this is a bug fix?):
Write.cpp: In member function `void* Write::initReadWrite()':
Write.cpp:516: error: invalid initialization of reference of type 'const volatile bool&' from expression of type 'volatile bool'
../../src/common/Assert.h:27: error: in passing argument 1 of `void unused(const T&) [with T = volatile bool]'
make[1]: *** [ARCH.cygwin/release/Write.o] Error 1
The argument to unused is a member variable declared as:
volatile bool readWriteActivated;
Is this a compiler bug or a bug in my code?
Here is the minimal test case:
template<typename T>
void unused(T const &) { }
int main() {
volatile bool x = false;
unused(!x); // type of "!x" is bool
}
The actual way of indicating you don't actually use a parameter is not giving it a name:
int f(int a, float) {
return a*2;
}
will compile everywhere with all warnings turned on, without warning about the unused float. Even if the argument does have a name in the prototype (e.g. int f(int a, float f);), it still won't complain.
I'm not 100% sure that this is portable, but this is the idiom I've usually used for suppressing warnings about unused variables. The context here is a signal handler that is only used to catch SIGINT and SIGTERM, so if the function is ever called I know it's time for the program to exit.
volatile bool app_killed = false;
int signal_handler(int signum)
{
(void)signum; // this suppresses the warnings
app_killed = true;
}
I tend to dislike cluttering up the parameter list with __attribute__((unused)), since the cast-to-void trick works without resorting to macros for Visual C++.
It is a compiler bug and there are no known work arounds:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42655
It is fixed in v4.4.
In GCC, you can define a macro as follows:
#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
# define UNUSED(x) /*#unused#*/ x
#else
# define UNUSED(x) x
#endif
Any parameters marked with this macro will suppress the unused warning GCC emits (and renames the parameter with a prefix of UNUSED_). For Visual Studio, you can suppress warnings with a #pragma directive.
The answer proposed by haavee (amended by ur) is the one I would normally use:
int f(int a, float /*epsilon*/) {
return a*2;
}
The real problem happens when the argument is sometimes but not always used in the method, e.g.:
int f(int a, float epsilon) {
#ifdef LOGGING_ENABLED
LOG("f: a = %d, epsilon = %f\n", a, epsilon);
#endif
return a*2;
}
Now, I can't comment out the parameter name epsilon because that will break my logging build (I don't want to insert another #ifdef in the argument list because that makes the code much harder to read).
So I think the best solution would be to use Tom's suggestion:
int f(int a, float epsilon) {
(void) epsilon; // suppress compiler warning for possibly unused arg
#ifdef LOGGING_ENABLED
LOG("f: a = %d, epsilon = %f\n", a, epsilon);
#endif
return a*2;
}
My only worry would be that some compilers might warn about the "(void) epsilon;" statement, e.g. "statement has no effect" warning or some such - I guess I'll just have to test on all the compilers I'm likely to use...