I have no problems implementing the memory mapped file. The question is. Assuming this returns a valid memory view.
void* pBuf = MapViewOfFile(hMapFile,
FILE_MAP_WRITE,
0,
0,
0);
Do i have alternatives to using memcpy to give data to it? for instance can i tell my application to store data in it? I really want something like char* buffer = new char[1073741824] where the new places the data in the memory mapped file. this seems logical. or will i have to write a wrapper that writes to the memory view using memcpy? that would be disapointing.
Probably the easiest approach is to use the boost memory mapped file classes which give the additional benefit of being portable.
You can use the placement new operator or you can cast the address to a structure or class you want to use. The advantage of placement new is that the constructor of the class will be called. If you use from then on that pointer you don't need to copy the data but read and write directly to it.
Related
I am trying to create buffer in a .js file, and then passing that buffer to a c++ addon where I will call a Windows API.
In the c++ addon I have:
auto buf = node::Buffer::Data(args[0]);
auto len = node::Buffer::Length(args[0]);
Are there any guarantees that node::Buffers are null-terminated? Or does node::Buffer::Length have any other form of safety check to prevent an overrun?
No. Think of buffers as a minimal data structure containing length and memory; they are not raw memory like what malloc() provides. A buffer is protected against memory overruns within a JavaScript context but not if you pass a pointer to the buffer memory to C/C++. And because a Buffer can be used to store binary data (as well as a string) it doesn't provide an extra byte to null-terminate a string; it doesn't "know" what is in the buffer.
I don't think the code you've posted will work; This post does a good job of explaining how to use buffers in C/C++: https://community.risingstack.com/using-buffers-node-js-c-plus-plus/
I know that the following is UB in c++ due how the standard defines lifetime, and how objects are allowed to be used:
Foo* foo = std::reinterpret_cast<Foo *>(malloc(sizeof(struct Foo)));
// read or write to foo
So to my understanding, the following would also be UB:
Foo * foo = std::reinterpret_cast<Foo *>(glMapNamedBuffer(/*...*/));
// read or write to foo
(Foo is a trivial copy and constructable object)
Based on that the pointer I get from glMapNamedBuffer can only be used in combination with std::memcpy to copy data from or into the memory block that pointer is addressing, but if this is the case isn't glMapNamedBuffer kinda useless in the context of c++, as I could use glGetNamedBufferSubData and glNamedBufferSubData instead as I need to copy the data anyway?
Or would the following also be UB and I would need to use a std::memcpy in any case:
Foo foo;
glNamedBufferSubData( 1, 0, sizeof(Foo), &foo);
Foo foo;
glGetNamedBufferSubData( 2, 0, sizeof(Foo), &foo);
I'm going to forget for the moment the fact that, as someone using a low-level API, you shouldn't be caring about undefined behavior of this sort, since this is pretty much what low-level programming is. So instead, we're in a world where we've decided that the only thing which matters is what the C++ standard actually says.
Given that:
So to my understanding, the following would also be UB:
Well, that rather depends: what is in that memory? Did you put an object there? Is the object you put there a Foo? If you didn't put a Foo there, you can put one there easily enough:
void *mem_ptr = glMapNamedBuffer(/*...*/);
Foo *ptr = new(mem_ptr) Foo;
Now there's a Foo there and we have a pointer to it. What's the problem? You can treat mapping a buffer as a fancy malloc.
Your next thought might be, but wait, what happens when I unmap the memory and map it again? Does OpenGL ensure that I'm getting a pointer to the same object? Could it be mapped to different addresses and break the C++ object model?
Again, given that we've decided to care about things that don't actually matter, OpenGL is entirely ignorant of the C++ object model. It's just looking at bytes of storage; that's all OpenGL preserves. Any particular mapping operation will only preserve the bytes, not the C++ objects around them (which are bound to memory addresses).
But we don't have to care about that if we persistently map buffers (which is the only way you should map buffers, given that you're clearly using APIs that require persistent mapped buffers to be available). There, you just map the pointer and you're done. You can do whatever you need with it.
And if you're reading data, you generally want that data out of the buffer object's memory ASAP. Reading from memory that is genuinely mapped to GPU memory can be exceedingly slow, so just doing a memcpy into an existing object would be appropriate. And with persistent mapped buffers, reading can be done after checking your fence to see if the data is available.
I have a situation where I need to send an object (which has pointers to dynamically allocated objects) from one process to anther process via IPC.
Blueprint of the class is:
class Example
{
std::string str;
char *cstring;
int value;
};
As you can see it has dynamically allocated data members that points to heap area mapped into that process.
If it was static object members then they are mapped in continuous memory allocation, and we can mem copy that object, right ? May be I am wrong or missing something.
Can we copy this entire object and send it over IPC, using any of the IPC mechanisms ?
Hope anyone of you can share some details how it will work or can be made to work by pointing me in right direction.
Thanks
Generally you need to serialise it into a sequential byte buffer, similar to how you might write or read say a file or over a network/internet. There are various libraries to help you with this, either with binary formats, or structured text like JSON or XML. Some may generate the boilerplate code for you to convert to and from structs or classes.
If you are using shared memory at the same virtual address, you could possibly take advantage of custom allocators to make sure STL types and other things store everything also in shared memory. I am not sure if the standard says anything much on if such use of shared memory for standard defined objects is technically compliant. I would expect string, vector, etc. to work, while things like mutex, fstream, etc. won't.
I'm looking for a way to automatically deallocate an array of wchar_ts – kind of like an autopointer (I'm not really aquainted with std::auto_ptr, but I think it cannot be used for arrays).
The code I have right now is this:
/* volume is of type wstring,
* hr is of type HRESULT,
* VSS_PWSZ equals wchar_t*
*/
VSS_PWSZ pwszVolume = new wchar_t[volume.size() + 1];
std::copy(volume.begin(), volume.end(), &pwszVolume);
pwszVolume[volume.size()] = 0;
hr = pDiffMgmt->QueryDiffAreasOnVolume(pwszVolume, &pEnumMgmt);
delete[] pwszVolume;
pwszVolume = NULL;
I don't really get why this stupid function cannot take a const wchar_t*, otherwise I could just pass volume.c_str().
So far so good, I think my code solves this problem, but now the memory management is getting more complicated: I would have to duplicate the delete[] code to account for exceptions which might be thrown (and which I do not want to catch at this point.)
Is there a way I can get pwszVolume to be deallocated automatically when the current scope is left?
Use std::vector<wchar_t> it is your basic C++ array (or std::wstring if you want to manipulate it like a string).
std::vector<wchar_t> pwszVolume(volume.begin(), volume.end());
pwszVolume.push_back(0);
hr = pDiffMgmt->QueryDiffAreasOnVolume(&pwszVolume[0], &pEnumMgmt);
The question may be. What does QueryDiffAreasOnVolume() do with the data?
Maybe you do not need to copy it out.
std::unique_ptr can be used with arrays as follows:
std::unique_ptr<wchar_t[]> pwszVolume(new wchar_t[volume.size() + 1]);
Another option is std::array.
But I agree with Martin's answer that you should just use an std::vector unless you really cannot afford to have the couple of extra pointers that the vector class holds.
As others have said, std::vector is the preferred solution, by far.
Otherwise (if e.g. you originally get the pointer from third party
software which you cannot modify), there's boost::scoped_array or
boost::shared_array.
If you don't want the overhead from std::vector, use boost::array. It is your basic C++ array with static size.
You can wrap wchar_t* inside a class, deallocate memory on destruct-or and you have an object that will be automatically deallocated when it loses scope.
I have programed an application on windows XP and in Visual Studio with c++ language.
In that app I used LoadResource() API to load a resource for giving a file in the resource memory.
It returned a pointer of memory block and I wanna cast the pointer to the std stream to use for compatibility.
Could anyone help me?
You can't cast the resource to a stream type. Either you copy the bytes:
std::stringstream ss;
ss.rdbuf().sputn(buf, len);
or you wrap your resource in your own streambuf:
class resourcebuf : public std::streambuf {
// Todo: implement members including at least xsgetn, uflow and underflow
};
and pass it to istream::istream
Why would you need this?
Casting raw data pointers to streams means byte-by-byte copying of your resource and, therefore, lacks in performance (and, also to mention, I don't see any benefit in this approach).
If you want to work with raw memory, work with it. Casting here (compatibility?) seems to be a very strange approach.
Still, if you want to do it, you could create some stream from your memory block, that treats it as a sequence of bytes. In this case, it means using std::stringstream (istringstream).
After you lock your resource by LockResource, create a string from received void* pointer and pass it to your stringstream instance.
void* memory = LockResource(...);
// You would probably want to use SizeofResource() here
size_t memory_size = ... ;
std::string casted_memory(static_cast<char*>(memory), memory_size);
std::istringstream stream(casted_memory);
Most straightforward way is probably to convert the buffer to string and then stringstream:
std::stringstream ss(std::string(buf,len));
I think that will copy it twice, though, so if it turns out to be taking a lot of time you might need to look for alternatives. You could use strstream, but it might freak out the squares.