0

How can I put this code in to a function so that I pass a file path and it returns the file-mapped bytes in to a char array? Whenever I have tried I can never read the contents once the function finishes?

using boost::interprocess;
using boost;

boost::shared_ptr<char> getBytes(const char* FilePath){
    shared_ptr<file_mapping> fm(new file_mapping(FilePath, read_only));
    shared_ptr<mapped_region> region(new mapped_region(*fm, read_only));
    shared_ptr<char> bytes(static_cast<char*>(region->get_address()));
    return bytes;
}
user997112
  • 29,025
  • 43
  • 182
  • 361
  • Hmya, RAII is not your friend here. That file_mapping is gonzo when the function returns. This requires a significant rewrite, like a little helper class that you return that stores the file_mapping and mapped_region so they can survive. – Hans Passant Nov 15 '13 at 23:23
  • So you're saying have a class where the byte array is a data member and may be the file gets mapped in the constructor? – user997112 Nov 15 '13 at 23:30
  • Yeah, something like that. This kind of usage of shared_ptr<> is cargo-cult, you are struggling with the fundamentals. Best way to get ahead is not use it for a while :) – Hans Passant Nov 15 '13 at 23:35

1 Answers1

0

You probably need to go about your objective quite differently! Clearly you don't want to just delete the pointer to the memory mapped array which is what the boost::shared_ptr<char> initialized with the pointer to the base address would do. In fact, you probably should not release that pointer at all.

The other two objects you create will go out of scope when getBytes() is exited but these are the objects which actually cling to the shared memory. What you might want to do is to put the file_mapping and the mapped_region together into an object which is put into the returned boost::shared_ptr<char> as a deleter object: this way these two objects would live long enough to keep the pointed to array alive. Upon the deleter function being called the two objects would be released. Here is how this would roughly look like although I haven't checked whether these are indeed the correct interfaces:

struct shared_memory_deleter
{
    shared_memory_deleter(char const* file)
        : d_fm(new file_mapping(file, read_only))
        , d_region(new mapped_region(*fm, read_only))
    {
    }
    void operator()(char*) {
        this->d_region.reset(0);
        this->d_fm.reset(0);
    }
    shared_ptr<file_mapping>  d_fm;
    shared_ptr<mapped_region> d_region);
};

boost::shared_ptr<char> getBytes(const char* FilePath){
    shared_memory_deleter deleter(FilePath);
    shared_ptr<char> bytes(deleter.d_region->get_address(), deleter);
    return bytes;
}

I'm not sure if this would work but it has, at least, a chance. It is probably not a good idea to do something like this. Instead, you are probably much better off wrapping the logic into an object and not using any shared pointers at all:

class shared_memory
{
public:
    shared_memory(char const* name)
        : d_file(name, read_only)
        , d_region(d_file, read_only)
    {
    }
    char const* buffer() const { return d_region.get_address(); }
};
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380