How to cast void* back to std::vector<float> - c++

I can construct data on Line 19 from vvp.at(0) if I know the size of vf.
#include <iostream>
#include <vector>
typedef void* VoidPointer;
typedef std::vector< float > VF;
typedef std::vector< VoidPointer > VVP;
int main(int argc, char** argv)
{
VF vf;
vf.push_back(13.0f);
vf.push_back(14.0f);
vf.push_back(15.0f);
vf.push_back(16.0f);
VVP vvp;
vvp.push_back( (VoidPointer)const_cast<float *>( &(vf.front()) ) );
VF data ( static_cast< float* >( vvp.at(0) ),
static_cast< float* >( vvp.at(0) ) + vf.size() );
std::cout << "data.size() is " << data.size() << std::endl;
for(VF::const_iterator i = data.begin(); i != data.end(); ++i)
{
std::cout << "data contains " << *i << std::endl;
}
return 0;
}
Leaving aside whether this is sensible (the example is contrived) I'd like to know how to cast vvp.at(0) to a std::vector<float> if I didn't know the size of vf. I'm thinking along the lines of something like:
std::vector<float> data( *static_cast< std::vector<float>* >( vvp.at(0) ) );
But that causes the program to termintate with std::bad_alloc, I don't mind copying if need be.

That is not a cast from vvp.at(0) to a vector, it's a copy of an array of floats into a new vector. And you can't copy it without knowing the length. You only saved a pointer to the first element, so the information was lost.
You could make std::vector<std::pair<VoidPointer, size_t> > VVP and save both &vf.front() and vf.size() (or start and end pointers, if you prefer).
You could make std::vector<VF *> and store pointers to vectors (i.e. vvp.push_back(&vf)) and now there's no casting at all.
Edit: In case you didn't realize: The pointer &vf is unrelated to &vf.front(). vf is a structure which contains the pointer &vf.front() (or a way to get it). There's no information in just the address &vf.front() to let you find &vf.

The only thing I can think of is extremely non-portable (and equally crazy). Each vector allocates a contiguous array of memory. Any allocation function has to keep track of how many bytes have been allocated, so that it can de-allocate them given only the beginning of the allocation's address.
AFAIK, the C++ standard does not specify how this book keeping is done and therefore, this up to each compiler. One method is to write a count before the actual allocation address - I believe this is what the Visual C++ compiler does. (Eg. if allocating at 0x104, a 32-bit count could be stored at 0x100). Again, you will have to know how your specific compiler does this book keeping.
Anyway, the point is, once you do, a little pointer arithmetic and de-referencing could theoretically look up the allocated size (I'm of course assuming you're still using a vector with a default allocator here), and figure out how many floats were actually allocated using only a void pointer.
Here's an example that works in Visual Studio in 32-bit debug mode:
#include <iostream>
#include <vector>
size_t bytes_allocated( void* p )
{
#ifndef _DEBUG
#error Doesn't work
#endif // _DEBUG
size_t const offset = 12;
size_t const counter_size = 4;
size_t const total_offset = offset + counter_size;
void* counter_address = ((char*)p)-total_offset;
size_t* count = reinterpret_cast<size_t*>(counter_address);
return *count;
}
int main(int argc, char* argv[])
{
typedef float test_type;
std::vector<test_type> v;
v.push_back(23);
v.push_back(23);
v.push_back(23);
size_t count = bytes_allocated(&v[0]);
std::cout<<count<<" bytes allocated\n";
std::cout<<count/sizeof(test_type)<<" items allocated\n";
return 0;
}
The output is:
12 bytes allocated
3 items allocated

Related

quickly cast a vector of unsigned char into a vector of POD struct and vice versa

I want to read/write binary data, essentially a vector of plain old data struct.
I managed to do so with arrays of char, but now I need to convert those arrays back and forth to an vector of struct.
I already managed to do this by reading/writing directly into files:
int main() {
struct thing { float f; char c; };
std::vector<thing> write_this = { {2,'c'},{5,'f'},{543,'e'} };
std::ofstream outfile{ "test.bin", std::ios::binary };
outfile.write(reinterpret_cast<const char *>(write_this.data()),
write_this.size() * sizeof(decltype(write_this)::value_type));
outfile.close();
std::vector<thing> result(3);
std::ifstream infile{ "test.bin", std::ios::binary };
infile.read(reinterpret_cast<char *>(result.data()),
result.size() * sizeof(thing));
for (auto& i : result)
std::cout << i.f << " " << i.c << ' ';
std::cout << '\n';
system("PAUSE");
return 0;
}
Since I want to store several different segments of data into a file, I'm using vectors of unsigned char as an intermediary. I now need to cast an array of char or vector of char to a vector of struct, and vice versa.
What's the simplest/cleanest/fastest way to do so?
Foreword: Note that the written data is not portable to other systems, and for some PODs (ones that contain bit fields) not even to other processes on same system compiled by a different compiler - unless those systems are somehow guaranteed to have identical binary representation.
Also, memory references in the written data will be meaningless to other processes, even to separate executions of the same program.
quickly cast a vector of unsigned char into a vector of POD struct and vice versa
You could do this:
static_assert(std::is_trivial_v<thing>);
constexpr int s = sizeof(thing);
int n = 3;
std::vector<unsigned char> result_raw(n * s);
unsigned char* data = result_raw.data();
infile.read(reinterpret_cast<char*>(data), n * s);
// ->
for(int i = 0; i < n; i++) {
unsigned char temp[s];
unsigned char* addr = data + i * s;
std::memcpy(temp, addr, s);
new (addr) thing;
std::memcpy(addr, temp, s);
}
thing* result = std::launder(reinterpret_cast<thing*>(data));
// <-
Now, you have a pointer to the first thing in the vector. Beautiful part about this is that the part between the arrow comments that creates the objects and makes the program well-defined compiles to zero instructions (as long as you enable optimisation).
You don't get a std::vector<thing> though. To get that, you must copy all of the from one vector another. Or you could read directly onto the vector of things like in your example. But you didn't want to do the latter, and former is slower than not copying.
In future, if p0593rX proposal is adopted, this block of code that does nothing could be greatly simplified.

Setting class level 2D Array variable to passed in value - C++

I'm attempting to make a maze-solving program, and while the algorithm is sound (at least in my head), I've been running into a roadblock with 2D arrays. I'm coming from C# and Java, so the syntax is giving me grief.
Here's an SSCCE:
//Main.cpp
#include "MazeSolver.h"
int main()
{
MazeSolver mazeSolver;
char maze[51][51] = { }; // Not bothering to show code for populating the array
mazeSolver.setMaze(maze);
}
//MazeSolver.cpp
#include "MazeSolver.h"
MazeSolver::MazeSolver() { }
void MazeSolver::setMaze(char maze[51][51])
{
this->maze = maze;
}
//MazeSolver.h
#ifndef _MAZESOLVER_H
#define _MAZESOLVER_H
class MazeSolver
{
private:
char **maze; // This is likely the problem, I'm at wits end in regards to
// what notation is needed here. I do not want to hard-copy
// the entire array, I just need to access it (via pointer)
// I've also tried just using char maze[51][51] here, char *maze, etc...
public:
MazeSolver();
void setMaze(char maze[51][51]);
}
You cant assign (Or convert) 2d arrays (array[ROWS][COLUMNS]) to pointers to pointers (aka **) because the memory layout of a 2d array is (could be) very different to the memory layout the pointer of pointers could point to.
Check this thread for more info about this topic.
If suggest you to use the de facto C++ standard container, std::vector, instead of a plain array:
class MazeSolver
{
std::vector<std::vector<char>> maze;
void setMaze( const std::vector<std::vector<char>>& new_maze )
{
maze = new_maze;
}
};
Note that a vector has size 0 by default (At the point of its initialization), so you should fill it with elements:
for( std::size_t i = 0 i < ROWS ; ++i )
{
maze.push_back( std::vector<char>() );
for( std::size_t j = 0 ; j < COLUMNS ; ++j )
maze[i].push_back( ' ' );
}
However, C++11 (The current iteration of the language) has a std::array container which is like a C array but with the interface of other Standard Library Containers:
std::array<char,ROWS*COLUMNS> maze;
<rant>
This is one of the weird quirks of C++.
C++ 2D arrays are NOT jagged arrays. When you declare char maze[51][51], it actually allocates 1 contiguous array 51*51 members long. sizeof(maze) == 51*51. When you dereference a value, maze[a][b], what it actually does is *(maze+51*a+b). All this is under the hood.
A Jagged Array is an array of arrays, a char**. In this case, you have an array of 51 pointers size == (51*sizeof(void*)). In each position, the pointer points to a completely different memory location, allocated to 51 members long.
This is ANNOYING because you can't just convert the two, even by casting. You have to deal with weird syntax, such as char (*maze)[51] to get a pointer to the 2D array.
Whats even more annoying is the following happens:
int foo(int maze[51][51])
{
return sizeof(maze);
}
int maze[51][51];
int main(int argc, char** argv)
{
std::cout << sizeof(maze) << std::endl;//return 51*51*sizeof(int);
std::cout << foo(maze) << std::endl;//return 8, sizeof(void*);
}
So it implicitly passes by reference, not by value, which is opposite all the rest of C++.
</rant>
tl;dr;
The correct syntax for a pointer to a 2D array is char (*maze)[51];. Your syntax is for a jagged array (arrays of arrays) which is NOT the same thing in C++.

2d thrust::device_vector to kernel

I have a data type defined as typedef InitialState float[12]. I have a vector containing several initial states defined by std::vector<InitialState> h_initials.
I made it a thrust device vector : thrust::device_vector<InitialState> d_initials = h_initials;
I would like to use this data is a user-defined kernel. However, I'm having problems casting it to a raw pointer. I've tried
float *p_initials = thrust::raw_pointer_cast(&d_initials[0]);
but thrust complains function returning array is not allowed.
Is there a way I can cast the device vector to a pointer that the kernel can use?
InitialState (float[12]) != float
InitialState *p_initials = thrust::raw_pointer_cast(d_initials.data());
float* p_floats = (float*)p_initials;
However, this is generally wrong to start with, because of the weird behavior below
typedef int int4[4];
void test(int4 a)
{
std::cout << sizeof(a) << std::endl;
}
int main(int argc, char** argv)
{
int4 f;
std::cout << sizeof(f) << std::endl;//returns 16 (4*sizeof(int))
test(f);//returns 8 (size of pointer, passes by reference)
}
Whats better is this:
struct InitialState{float value[12];}
std::vector<InitialState> h_initials;
thrust::device_vector<InitialState> d_initials = h_initials;
InitialState *p_initials = thrust::raw_pointer_cast(d_initials.data());
float* p_floats = (float*)p_initials;
And in cuda, you can use either InitialState* or float* as the argument (though SOA works better than AOS)

C++: Trouble with Pointers, loop variables, and structs

Consider the following example:
#include <iostream>
#include <sstream>
#include <vector>
#include <wchar.h>
#include <stdlib.h>
using namespace std;
struct odp {
int f;
wchar_t* pstr;
};
int main()
{
vector<odp> vec;
ostringstream ss;
wchar_t base[5];
wcscpy_s(base, L"1234");
for (int i = 0; i < 4; i++)
{
odp foo;
foo.f = i;
wchar_t loopStr[1];
foo.pstr = loopStr; // wchar_t* = wchar_t ? Why does this work?
foo.pstr[0] = base[i];
vec.push_back(foo);
}
for (vector<odp>::iterator iter = vec.begin(); iter != vec.end(); iter++)
{
cout << "Vec contains: " << iter->f << ", " << *(iter->pstr) << endl;
}
}
This produces:
Vec contains: 0, 52
Vec contains: 1, 52
Vec contains: 2, 52
Vec contains: 3, 52
I would hope that each time, iter->f and iter->pstr would yield a different result. Unfortunately, iter->pstr is always the same.
My suspicion is that each time through the loop, a new loopStr is created. Instead of copying it into the struct, I'm only copying a pointer. The location that the pointer writes to is getting overwritten.
How can I avoid this? Is it possible to solve this problem without allocating memory on the heap?
What you've got here is undefined behavior. Each time through your loop you create and destroy an array and then assign its address to foo.pstr and push it back into your vector. The compiler just happens to create that array in the same place every time (which is logical but not necessary). When you print it out you're technically printing out deleted data it's just that the system isn't bitch slapping you for it because it's not protected space. The memory location simply has whatever it was assigned last.
You fix this by discontinuing the use of raw character pointers and arrays.
...
odp foo;
foo.f = i;
wchar_t loopStr[1]; //A
foo.pstr = loopStr; //B
foo.pstr[0] = base[i]; //C
vec.push_back(foo);
...
A - You allocate an array (of size 1) to the stack
B - You assign foo.pstr to point to the array on the stack
C - You assign base[i] to the first element of the array (which is on the stack)
After the for loop exits its current cycle the variable loopStr is no longer in scope and its content is undefined. The next loop iteration will most likley re-use the same memory address (hence why you get the same value when you print at the end). If you have optimisations turned on your C compiler may be able to warn you about taking addresses of local variables (although I doubt it).
Without using any heap allocation I would think your only option is to fix the size of foo.pstr in odp, i.e.
struct odp {
int f;
wchar_t pstr[1];
};
or allocate the array on the heap as part of the odp initialisation
...
odp foo;
foo.f = i;
foo.pstr = new wchar_t [1];
foo.pstr[0] = base[i];
vec.push_back(foo);
...
better still use std::wstring since you are using c++, and let it do the memory allocation and management for you.
It looks like pstr is pointing to the locally scoped variable loopStr, so the results are undefined (it appears to still have the last stored value in it when printing the results). If you printed the address of pstr in the loop, I believe it would be the same for each position in the loop.
foo.pstr = loopStr; // wchar_t* = wchar_t ? Why does this work?
This doesn't work, at least not in the way you want it to. loopStr is an array, but you can use it like a pointer too. So when you assign to the pointer foo.pstr, it gets the address of the first element in loopStr. That happens to be a local variable allocated on the stack and is only valid inside the for loop.

Looking at the C++ new[] cookie. How portable is this code?

I came up with this as a quick solution to a debugging problem - I have the pointer variable and its type, I know it points to an array of objects allocated on the heap, but I don't know how many. So I wrote this function to look at the cookie that stores the number of bytes when memory is allocated on the heap.
template< typename T >
int num_allocated_items( T *p )
{
return *((int*)p-4)/sizeof(T);
}
//test
#include <iostream>
int main( int argc, char *argv[] )
{
using std::cout; using std::endl;
typedef long double testtype;
testtype *p = new testtype[ 45 ];
//prints 45
std::cout<<"num allocated = "<<num_allocated_items<testtype>(p)<<std::endl;
delete[] p;
return 0;
}
I'd like to know just how portable this code is.
It is not even remotely portable.
An implementation can perform heap bookkeeping however it wants and there is absolutely no way to portably get the size of a heap allocation unless you keep track of it yourself (which is what you should be doing).
You can globally overload new/delete operators on array, and put the size into the memory area. You get a portable solution.
The below code shows how:
void * operator new [] (size_t size)
{
void* p = malloc(size+sizeof(int));
*(int*)p = size;
return (void*)((int*)p+1);
}
void operator delete [] (void * p)
{
p = (void*)((int*)p-1);
free(p);
}
template<typename T>
int get_array_size(T* p)
{
return *((int*)p-1)/sizeof(T);
}
int main(int argc, char* argv[])
{
int* a = new int[200];
printf("size of a is %d.\n", get_array_size(a));
delete[] a;
return 0;
}
Result:
size of a is 200.
Not portable. But why not use std::vector? Then you can ask it directly how many elements it contains, and you won't need to worry about memory management and exception safety.