I would like to copy the address of an object to a buffer and typecast it back at some other point. I am unable to do it. A sample code is given below.
#include <iostream>
#include <cstring>
class MyClass
{
public:
MyClass(const int & i)
{
id = i;
}
~MyClass()
{
}
void print() const
{
std::cout<<" My id: "<<id<<std::endl;
}
private:
int id;
};
int main()
{
MyClass *myClass = new MyClass(10);
std::cout<<"myClass: "<<myClass<<std::endl;
myClass->print();
// Need to copy the address to a buffer and retrieve it later
char tmp[128];
// std::vector tmp(sizeof(myClass); // preferably, we may use this instead of the previous line, and use std::copy instead of memcpy
memcpy(tmp, myClass, sizeof(myClass));
// retreiving the pointer
MyClass* myClassPtr = (MyClass*) tmp;
std::cout<<"myClassPtr: "<<myClassPtr<<std::endl;
myClassPtr->print();
return 0;
}
In fact, the pointers gives different values, which is the source of the problem. What am I doing wrong here?
You are copying (a pointer-sized part of) the object itself, not the pointer. You should do:
memcpy(tmp, &myClass, sizeof(myClass));
and then back:
MyClass *ptr;
memcpy(&ptr, tmp, sizeof(ptr));
Related
Why this can't work. Is there any way to do this?
I don't want to create a separate function for pointers
#include <iostream>
using namespace std;
template<class T>
class temp
{
public:
T val;
temp(T value) : val(value) {}
~temp()
{
if(is_pointer<T>::value)
{
delete val;
}
}
};
int main()
{
string * n = new string("cat");
temp<string*>object(n);//ok
temp<string>object2("dog"); //compliation error: type 'class std::cxx11::basic_string' argument given to 'delete', expected pointer. --- (but there is if statement!!!!)
//i dont want delete in main
return 0;
}
To compile i use g++ 6.3.0
Could someone help? Maybe, I need to separate declaration from definition?
The issue that you have is that the branch of an if must always be syntactically valid, even if it is never taken.
You could do it with if constexpr, which is a "compile time if"
~temp()
{
if constexpr(is_pointer<T>::value)
{
delete val;
}
}
However this isn't safe.
How do you know that the pointer passed to temp<T*> was created by new and not new[], malloc, or by taking the address of an object that wasn't dynamically allocated?
Rather than assume that pointers should be deleted, you should avoid having to know which pointers to delete
#include <string>
#include <memory>
template<class T>
class temp
{
public:
T val;
temp(T value) : val(value) {}
// n.b. no need to define destructor
};
int main()
{
std::string str("cat");
temp<std::string*> object(&str);//ok
temp<std::string> object2("dog"); // also ok
std::unique_ptr<std::string> str2 = std::make_unique<std::string>("mouse");
temp<std::string *> object3(str2.get()); // ok so long as str2 outlives object3
std::shared_ptr<std::string> str3 = std::make_shared<std::string>("rabbit");
temp<std::shared_ptr<std::string>> object4(str3); // also ok
return 0;
}
There are situations in which I need to pass a char* buffer back and forth. My idea is to create an object which can hold the object that owns the data, but also expose the data as char* for someone to read. Since this object holds the owner, there are no memory leaks because the owner is destructed with the object when it's no longer necessary.
I came with the implementation below, in which we have a segfault that I explain why it happens. In fact it's something that I know how to fix but it's something that my class kinda lured me into doing. So I consider what I've done to be not good and maybe there's a better way of doing this in C++ that is safer.
Please take a look at my class that holds the buffer owner and also holds the raw pointer to that buffer. I used GenericObjectHolder to be something that holds the owner for me, without my Buffer class being parametrized by this owner.
#include <iostream>
#include <string>
#include <memory>
#include <queue>
//The library:
class GenericObjectHolder
{
public:
GenericObjectHolder()
{
}
virtual ~GenericObjectHolder() {
};
};
template <class T, class Holder = GenericObjectHolder>
class Buffer final
{
public:
//Ownership WILL be passed to this object
static Buffer fromOwned(T rawBuffer, size_t size)
{
return Buffer(std::make_unique<T>(rawBuffer), size);
}
//Creates a buffer from an object that holds the buffer
//ownership and saves the object too so it's only destructed
//when this buffer itself is destructed
static Buffer fromObject(T rawBuffer, size_t size, Holder *holder)
{
return Buffer(rawBuffer, std::make_unique<T>(rawBuffer), size, holder);
}
//Allocates a new buffer with a size
static Buffer allocate(size_t size)
{
return Buffer(std::make_unique<T>(new T[size]), size);
}
~Buffer()
{
if (_holder)
delete _holder;
}
virtual T data()
{
return _rawBuffer;
}
virtual size_t size() const
{
return _size;
}
Buffer(T rawBuffer, std::unique_ptr<T> buffer, size_t size)
{
_rawBuffer = rawBuffer;
_buffer = std::move(buffer);
_size = size;
}
Buffer(T rawBuffer, std::unique_ptr<T> buffer, size_t size, Holder *holder)
{
_rawBuffer = rawBuffer;
_buffer = std::move(buffer);
_size = size;
_holder = holder;
}
Buffer(const Buffer &other)
: _size(other._size),
_holder(other._holder),
_buffer(std::make_unique<T>(*other._buffer))
{
}
private:
Holder *_holder;
T _rawBuffer;
std::unique_ptr<T> _buffer;
size_t _size = 0;
};
//Usage:
template <class T>
class MyHolder : public GenericObjectHolder
{
public:
MyHolder(T t) : t(t)
{
}
~MyHolder()
{
}
private:
T t;
};
int main()
{
std::queue<Buffer<const char*, MyHolder<std::string>>> queue;
std::cout << "begin" << std::endl;
{
//This string is going to be deleted, but `MyHolder` will still hold
//its buffer
std::string s("hello");
auto h = new MyHolder<std::string>(s);
auto b = Buffer<const char*, MyHolder<std::string>>::fromObject(s.c_str(),s.size(), h);
queue.emplace(b);
}
{
auto b = queue.front();
//We try to print the buffer from a deleted string, segfault
printf(b.data());
printf("\n");
}
std::cout << "end" << std::endl;
}
As you see, the s string is copied inside the object holder but gets destructed right after it. So when I try to access the raw buffer that buffer owns I get a segfault.
Of course I could simply copy the buffer from the s string into a new buffer inside my object, but It'd be inefficient.
Maybe there's a better way of doing such thing or maybe there's even something ready in C++ that does what I need.
PS: string is just an example. In pratice I could be dealing with any type of object that owns a char* buffer.
Live example: https://repl.it/repls/IncredibleHomelySdk
Your core problem is that you want your Holder to be moveable. But when the Owner object moves, the buffer object might also move. That will invalidate your pointer. You can avoid that by putting the owner in a fixed heap location via unique_ptr:
#include <string>
#include <memory>
#include <queue>
#include <functional>
template <class B, class Owner>
class Buffer
{
public:
Buffer(std::unique_ptr<Owner>&& owner, B buf, size_t size) :
_owner(std::move(owner)), _buf(std::move(buf)), _size(size)
{}
B data() { return _buf; }
size_t size() { return _size; }
private:
std::unique_ptr<Owner> _owner;
B _buf;
size_t _size;
};
//Allocates a new buffer with a size
template<typename T>
Buffer<T*, T[]> alloc_buffer(size_t size) {
auto buf = std::make_unique<T[]>(size);
return {std::move(buf), buf.get(), size};
}
Here's a repl link: https://repl.it/repls/TemporalFreshApi
If you want to have a type-erased Buffer, you can do that like this:
template <class B>
class Buffer
{
public:
virtual ~Buffer() = default;
B* data() { return _buf; }
size_t size() { return _size; }
protected:
Buffer(B* buf, size_t size) :
_buf(buf), _size(size) {};
B* _buf;
size_t _size;
};
template <class B, class Owner>
class BufferImpl : public Buffer<B>
{
public:
BufferImpl(std::unique_ptr<Owner>&& owner, B* buf, size_t size) :
Buffer<B>(buf, size), _owner(std::move(owner))
{}
private:
std::unique_ptr<Owner> _owner;
};
//Allocates a new buffer with a size
template<typename T>
std::unique_ptr<Buffer<T>> alloc_buffer(size_t size) {
auto buf = std::make_unique<T[]>(size);
return std::make_unique<BufferImpl<T, T[]>>(std::move(buf), buf.get(), size);
}
Again, repl link: https://repl.it/repls/YouthfulBoringSoftware#main.cpp
You wrote:
There are situations in which I need to pass a char* buffer back and
forth.
and
So I consider what I've done to be not good and maybe there's a better
way of doing this in C++ that is safer.
It's not exactly clear what you are aiming at, but when I have this need i will sometimes use std::vector<char> - a std::vector (and std::string) is a just that: a managed buffer. Calling data() on vector will give you a raw pointer to the buffer to pass on to legacy interfaces etc. or for whatever reason you just need a buffer that you manage yourself. Hint: use resize() or constructor to allocate the buffer.
So you see, there's no need to store the internal pointer of std::string in your example. Instead just call data() on a need basis.
It seems like you are concerned about copies and efficiency. If you use objects that support move semantics and you use the emplace family of functions there shouldn't be any copy-ing going on at least in c++17. All/most containers supports moving as well.
The class std::unique_ptr is already a "buffer holder" that "guarantee delete", no string copies, no dangling references and no seg faults:
#include <iostream>
#include <queue>
#include <memory>
int main()
{
std::queue<std::unique_ptr<std::string>> queue;
std::cout << "begin" << std::endl;
{
auto h = std::make_unique<std::string>("Hello");
queue.emplace( std::move(h) ); // move into the queue without copy
}
{
auto b = std::move(queue.front()); // move out from queue without copy
std::cout << *b << std::endl;
} // when b goes out of scope it delete the string
std::cout << "end" << std::endl;
}
https://godbolt.org/z/neP838
So I have my class Test.H which has a struct in it.
Class Test{
private:
struct Data
{
char *first;
int number;
int count;
};
Data *myStruct;
I am trying to use the myStruct in my User.C initialiser.
//User.C
#include "Test.H"
Test::Test(const char *alp){
myStruct.number = 0;
}
And I get an segmentation fault and error from valgrind.
I figured initially that it was due to Data* myStruct being in private, but after writing a function like this below:
Data getStruct(){
return myStruct;
}
It will still give me errors when I use it in User.C
You need to construct the struct before you can do anything with it. Calling the default constructor will initialises it's fields to 0.
You had class capitalised, that was wrong. I also don't see a reason why it has to be a pointer, so I removed that. Lastly, I added a destructor in Data so that first will be deleted. I assume it is a cstring, so I used delete[]. If it is something else, delete it in whatever manner is appropriate.
If you must have a pointer, modify the call to the constructor to use new, delete the struct in the destructor ~Test(), and reference members of myStruct with the -> operator.
class Test {
public:
struct Data {
const char* first;
int number;
int count;
~Data() {
delete[] first;
}
};
Test(const char *alp) {
// Default constructor initialises struct's fields to 0.
myStruct = Data();
myStruct.count = 7;
}
private:
Data myStruct;
};
I'm trying to return pointer from function in derived class,
This is the code:
class A
class A {
protected:
C c;
public:
virtual void func(){
unsigned char *data;
int size=getData(data);
}
}
class B
class B : public A {
private:
int size;
public:
B(const C &_c) { c=_c; };
const int B::getData(unsigned char *data) const {
data=(unsigned char *)malloc(size);
memcpy(data,c.getMem(),size);
if(!data){
//err
}
return size;
}
class C
class C {
private:
unsigned char *mem;
public:
C(unsigned char *_mem) : mem(_mem);
const unsigned char *getMem() const { return mem; };
}
main.cpp
C c(...);
B *b=new B(c);
b->func();
The error I get when getData returns
(this=0x50cdf8, data=0x2 <error: Cannot access memory at address 0x2>, size=32)
Thanks.
In class A, the func() is worthless because:
1. size is not returned to the caller.
2. The pointer data is local to func and it's contents will disappear after the end of execution in func().
You don't need to return const int from a function. A function will return a copy of variables, so they are constant (copies).
Don't use malloc in C++, use operator new. The malloc function does not call constructors for objects.
Don't use new or malloc unless absolutely necessary. Usually, dynamic memory is for containers where their capacity is not known at compile time; or for objects that live beyond a function or statement block's execution time. If you must use dynamic memory, use a smart pointer (like boost::shared_ptr).
Use std::vector for dynamic arrays. It works; it's been tested; you don't have to write your own, including memory management.
You are passing data by value (a copy of the pointer). If you want to modify a pointer, pass it by reference or pass a pointer to the pointer; (what I call the address of the pointer).
Example:
void my_function(uint8_t * & p_data)
{
p_data = new uint8_t[512];
}
Or
void another_function(unsigned char * * pp_data)
{
*pp_data = new unsigned char [1024];
}
A much better solution:
void better_function(std::vector<uint8_t>& data)
{
data.reserve(64);
for (uint8_t i = 0; i < 64; ++i)
{
data[i] = i;
}
}
I run in to segmentation faults when running this code (no compiler warnings or errors).
It occurs when trying to assign "Test" to str->sString
MyClass.cpp
//Constructor
MyClass::MyClass( MyStruct *pDesc )
{
pDesc = new MyStruct();
//This is where I get a segmentation fault
pDesc->bar= 0xFF;
}
MyClass.hpp
class ClGadgetFs
{
public:
struct MyStruct{
int bar;
};
MyClass(MyStruct *pDesc = NULL);
};
I thought when calling new I would be aalocating memory for the struct? Like malloc(sizeof(myStruct))
Where am I wrong?
void setStruct(myStruct *str)
{
str->sString = "Test";
str->nNo = 4;
}
int main()
{
myStruct p;
setStruct(&p);
return 0;
}
you can do this instead
Edit
int main()
{
MyStruct *pDesc;
MyClass myClassInstance( pDesc );
std::cout<< pDesc->bar << std::endl;
return 0;
}
and
MyClass::MyClass( MyStruct *pDesc )
should be changed to
MyClass::MyClass( MyStruct *& pDesc )
void setStruct(myStruct*& str)
The above is probably what you want: changing the passed pointer, as output parameter.
#include <string>
struct myStruct
{
std::string sString;
int nNo;
};
void setStruct(myStruct **str)
{
*str = new myStruct();
(*str)->sString = "Test";
(*str)->nNo = 4;
}
int main()
{
myStruct *p;
setStruct(&p);
}
should be what you want, this is the C-style of passing the pointer; since you're allocating memory for the passed pointer, passing the pointer alone doesn't work, you should pass the pointer's address. Another way would be a reference to the pointer that Joop Eggen's answer points out.
str in the function setStruct is a local variable, whose life time is limited in this function.
So when new returns the address, there is no effect on the actual parameter. It is just the same to
void func(int a){
a = 4
}
You should use pointer to pointer or reference
void setStruct(myStruct ** str){
(*str) = new myStruct();
(*str)->sString = "Test";
(*str)->nNo = 4;
}
void setStruct(myStruct *& str){
str = new myStruct();
str->sString = "Test";
str->nNo = 4;
}
You should use a reference to your pointer to modify it in your function:
struct myStruct{
std::string sStrnig;
int nNo;
};
void setStruct(myStruct* &str){
str = new myStruct();
str->sString = "Test";
str->nNo = 4;
}
main(){
struct myStruct *str = 0;
setStruct( str );
}
It's likely that the caller of setStruct is allocating a myStruct on the stack:
myStruct value;
and you are calling setStruct(&value);
That would cause the segmentation fault as you would be attempting to rearrange the stack memory.
It's difficult to say anything else without the complete example though.
There's nothing wrong with the code as it stands aside from the fact that the value of the pointer following str = new myStruct(); is not passed back to the caller: the caller would be still referring to the pointer pointing to unallocated memory which would result in undefined behaviour. But that is not causing your crash since given where you say the error happens.
A simple fix would be to change the function prototype to
void setStruct(myStruct*& str)
i.e. pass the pointer by reference so the caller get's the modified pointer value back.