Visual C++: How is checked_array_iterator useful? - visual-c++

On compiling code at Warning Level 4 (/W4), I get C4996 warnings on std::copy() calls whose parameters are C arrays (not STL containers like vectors). The recommended solution to fix this seems to be to use stdext::checked_array_iterator.
What is the use of stdext::checked_array_iterator? How does it work?
Why does it not give any compile warning on this piece of erroneous code compiled under Visual C++ 2010?:
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
int arr0[5] = {100, 99, 98, 97, 96};
int arr1[3];
copy( arr0, arr0 + 5, stdext::checked_array_iterator<int*>( arr1, 3 ) );
return 0;
}

This page, Checked Iterators, describe how it works, but this quote sums it up: Checked iterators ensure that you do not overwrite the bounds of your container.
So if you go outside the bounds of the iterator it'll either throw and exception or call invalid_parameter.

Related

Enabling string conversion functions in MinGW

this code:
#include <iostream>
#include <string>
int main()
{
std::string s = "52123210";
int derp = std::stoi(s, 0, 10);
std::to_string(derp);
return 0;
}
with this error:
test.cpp:10:2: error: 'stoi' is not a member of 'std'
test.cpp:11:2: error: 'to_string' is not a member of 'std'
tried this:
http://tehsausage.com/mingw-to-string
(not work)
Update my MingW from 4.6.1 to 4.8.1
(not work)
possible bug:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37522
(beyond of my knowledge to apply anything, I don't dare to touch the compiler's code)
**Also not work with "using namespace std" but produced 'stoi' and 'to_string' not declared
error instead.
This is a result of a non-standard declaration of vswprintf on Windows. The GNU Standard Library defines _GLIBCXX_HAVE_BROKEN_VSWPRINTF on this platform, which in turn disables the conversion functions you're attempting to use.
https://stackoverflow.com/a/8543540/2684539 proposes a hack/work around.

CUDA - Array Generating random array on gpu and its modification using kernel

in this code im generating 1D array of floats on a gpu using CUDA. The numbers are between 0 and 1. For my purpose i need them to be between -1 and 1 so i have made simple kernel to multiply each element by 2 and then substract 1 from it. However something is going wrong here. When i print my original array into .bmp i get this http://i.imgur.com/IS5dvSq.png (typical noise pattern). But when i try to modify that array with my kernel i get blank black picture http://imgur.com/cwTVPTG . The program is executable but in the debug i get this:
First-chance exception at 0x75f0c41f in Midpoint_CUDA_Alpha.exe:
Microsoft C++ exception: cudaError_enum at memory location
0x003cfacc..
First-chance exception at 0x75f0c41f in Midpoint_CUDA_Alpha.exe:
Microsoft C++ exception: cudaError_enum at memory location
0x003cfb08..
First-chance exception at 0x75f0c41f in Midpoint_CUDA_Alpha.exe:
Microsoft C++ exception: [rethrow] at memory location 0x00000000..
i would be thankfull for any help or even little hint in this matter. Thanks !
(edited)
#include <device_functions.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "stdafx.h"
#include "EasyBMP.h"
#include <curand.h> //curand.lib must be added in project propetties > linker > input
#include "device_launch_parameters.h"
float *heightMap_cpu;
float *randomArray_gpu;
int randCount = 0;
int rozmer = 513;
void createRandoms(int size){
curandGenerator_t generator;
cudaMalloc((void**)&randomArray_gpu, size*size*sizeof(float));
curandCreateGenerator(&generator,CURAND_RNG_PSEUDO_XORWOW);
curandSetPseudoRandomGeneratorSeed(generator,(int)time(NULL));
curandGenerateUniform(generator,randomArray_gpu,size*size);
}
__global__ void polarizeRandoms(int size, float *randomArray_gpu){
int index = threadIdx.x + blockDim.x * blockIdx.x;
if(index<size*size){
randomArray_gpu[index] = randomArray_gpu[index]*2.0f - 1.0f;
}
}
//helper fucnction for getting address in 1D using 2D coords
int ad(int x,int y){
return x*rozmer+y;
}
void printBmp(){
BMP AnImage;
AnImage.SetSize(rozmer,rozmer);
AnImage.SetBitDepth(24);
int i,j;
for(i=0;i<=rozmer-1;i++){
for(j=0;j<=rozmer-1;j++){
AnImage(i,j)->Red = (int)((heightMap_cpu[ad(i,j)]*127)+128);
AnImage(i,j)->Green = (int)((heightMap_cpu[ad(i,j)]*127)+128);
AnImage(i,j)->Blue = (int)((heightMap_cpu[ad(i,j)]*127)+128);
AnImage(i,j)->Alpha = 0;
}
}
AnImage.WriteToFile("HeightMap.bmp");
}
int main(){
createRandoms(rozmer);
polarizeRandoms<<<((rozmer*rozmer)/1024)+1,1024>>>(rozmer,randomArray_gpu);
heightMap_cpu = (float*)malloc((rozmer*rozmer)*sizeof(float));
cudaMemcpy(heightMap_cpu,randomArray_gpu,rozmer*rozmer*sizeof(float),cudaMemcpyDeviceToHost);
printBmp();
//cleanup
cudaFree(randomArray_gpu);
free(heightMap_cpu);
return 0;
}
This is wrong:
cudaMalloc((void**)&randomArray_gpu, size*size*sizeof(float));
We don't use cudaMalloc with __device__ variables. If you do proper cuda error checking I'm pretty sure that line will throw an error.
If you really want to use a __device__ pointer this way, you need to create a separate normal pointer, cudaMalloc that, then copy the pointer value to the device pointer using cudaMemcpyToSymbol:
float *my_dev_pointer;
cudaMalloc((void**)&my_dev_pointer, size*size*sizeof(float));
cudaMemcpyToSymbol(randomArray_gpu, &my_dev_pointer, sizeof(float *));
Whenever you are having trouble with your CUDA programs, you should do proper cuda error checking. It will likely focus your attention on what is wrong.
And, yes, kernels can access __device__ variables without the variable being passed explicitly as a parameter to the kernel.
The programming guide covers the proper usage of __device__ variables and the api functions that should be used to access them from the host.

trouble with .inl files c++

i have a trouble with a function template implementation in a .inl file (visual c++)
I have this on a header file.
math.h ->>
#ifndef _MATH_H
#define _MATH_H
#include <math.h>
template<class REAL=float>
struct Math
{
// inside this structure , there are a lot of functions , for example this..
static REAL sin ( REAL __x );
static REAL abs ( REAL __x );
};
#include "implementation.inl" // include inl file
#endif
and this is the .inl file.
implementation.inl -->>
template<class REAL>
REAL Math<REAL>::sin (REAL __x)
{
return (REAL) sin ( (double) __x );
}
template<class REAL>
REAL Math<REAL>::abs(REAL __x)
{
if( __x < (REAL) 0 )
return - __x;
return __x;
}
the sine function throw me an error at run time when i call it. However , abs function works
correctly.
i think the trouble is the call to one of the functions of the header math.h inside the .inl files
why I canĀ“t use math.h functions inside .inl file ?
The problem has nothing to do with .inl files - you're simply calling Math<REAL>::sin() recursively until the stack overflows. In MSVC 10 I even get a nice warning pointing that out:
warning C4717: 'Math<double>::sin' : recursive on all control paths, function will cause runtime stack overflow
Try:
return (REAL) ::sin ( (double) __x ); // note the `::` operator
Also, as a side note: the macro name _MATH_H is reserved for use by the compiler implementation. In many cases of using an implementation-reserved identifier you'd be somewhat unlucky to actually run into a conflict (though you should still avoid such names). However, in this case that name has a rather high chance of conflicting with the one that math.h might actually be using to prevent itself from being included multiple times.
You should definitely choose a different name that's unlikely to conflict. See What are the rules about using an underscore in a C++ identifier? for the rules.

MSVC doesn't expand __VA_ARGS__ correctly

Consider this code:
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) F(__VA_ARGS__)
F(1, 2, 3)
G(1, 2, 3)
The expected output is X = 1 and VA_ARGS = 2, 3 for both macros, and that's what I'm getting with GCC, however, MSVC expands this as:
X = 1 and VA_ARGS = 2, 3
X = 1, 2, 3 and VA_ARGS =
That is, __VA_ARGS__ is expanded as a single argument, instead of being broken down to multiple ones.
Any way around this?
Edit:
This issue might be resolved by using
/Zc:preprocessor or /experimental:preprocessor option in recent MSVC.
For the details, please see
here.
MSVC's preprocessor seems to behave quite differently from the standard
specification.
Probably the following workaround will help:
#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )
I posted the following Microsoft support issue:
The following program gives compilation error because the precompiler
expands __VA_ARGS__ incorrectly:
#include <stdio.h>
#define A2(a1, a2) ((a1)+(a2))
#define A_VA(...) A2(__VA_ARGS__)
int main(int argc, char *argv[])
{
printf("%d\n", A_VA(1, 2));
return 0;
}
The preprocessor expands the printf to:
printf("%d\n", ((1, 2)+()));
instead of
printf("%d\n", ((1)+(2)));
I received the following unsatisfying answer from a Microsoft compiler team developer:
Hi: The Visual C++ compiler is behaving correctly in this case. If you combine the rule that tokens that match the '...' at the inital macro invocation are combined to form a single entity (16.3/p12) with the rule that sub-macros are expanded before argument replacement (16.3.1/p1) then in this case the compiler believes that A2 is invoked with a single argument: hence the error message.
What version of MSVC are you using? You will need Visual C++ 2010.
__VA_ARGS__ was first introduced by C99. MSVC never attempted to support C99, so the support was not added.
Now, however, __VA_ARGS__ is included in the new C++ standard, C++2011 (previously known as C++0x), which Microsoft apparently plans to support, so it has been supported in recent versions of MSVC.
BTW, you will need to use a .cpp suffix to your source file to get this support. MSVC hasn't updated its C frontend for a long time.

How to use set_intersection with std::set in VC++?

I'm trying to compile VC6 project with VC10...
I obtain an error C2678 with set_intersection: I wrote some example to understand. Can anybody explain how to compile this snippets ?
#include <vector>
#include <algorithm>
#include <iostream>
#include <set>
#include <string>
int main( )
{
using namespace std;
typedef set<string> MyType;
MyType in1, in2, out;
MyType::iterator out_iter(out.begin());
set_intersection(in1.begin(),in1.end(), in2.begin(), in2.end(), out_iter);
}
The output :
c:\program files\microsoft visual\studio 10.0\vc\include\algorithm(4494): error C2678: '=' binary : no operator defined which takes a left-hand operand of type 'const std::basic_string<_Elem,_Traits,_Ax>' (or there is no acceptable conversion)
If I use a std::vector instead of std::set the compilation succeeded.
acceptable)
Try
set_intersection(in1.begin(),in1.end(), in2.begin(), in2.end(), inserter(out, out.begin()) );
This is because set_intersection wants to write to the output iterator, which causes the output container to grow in size. However this couldn't be done with just an iterator alone (it could be used to overwrite existing elements but not grow in size)
Edit: fixed the typo. Use inserter for adding to a set. A back_inserter only works for vectors and such.
Edit 2: fixed another typo. STL inserter requires a second argument which is a hint iterator to the likely insert position. Thanks chepseskaf.

Resources