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;
}
}
Related
A fairly common thing I need to do is allot an object and some memory it'd like, in a strictly contagious region of memory together:
class Thing{
static_assert(alignof(Thing) == alignof(uint32), "party's over");
public:
~Thing(){
//// if only, but this would result in the equivalent of `free(danglingPtr)` being called
//// as the second stage of shared_ptr calling `delete this->get()`, which can't be skipped I believe?
// delete [] (char*)this;
}
static Thing * create(uint32 count) {
uint32 size = sizeof(Thing) + sizeof(uint32) * count; // no alignment concerns
char * data = new char[size];
return new (data)Thing(count);
}
static void destroy(Thing *& p) {
delete [] (char*)p;
p = NULL;
}
uint32 & operator[](uint32 index) {
assert(index < m_count);
return ((uint32*)((char*)(this + sizeof(Thing))))[index];
}
private:
Thing(uint32 count) : m_count(count) {};
uint32 m_count;
};
int main(){
{
auto p = shared_ptr<Thing>(Thing::create(1));
// how can I tell p how to kill the Thing?
}
return 0;
}
In Thing::Create() this is done with placement new into a section of memory.
I'd also like to have a shared pointer manage it in this case, using auto p = shared_ptr<Thing>(Thing::create(1)). But If it calls the equivalent of delete p.get() when the ref count empties, that'd be undefined as it mismatches the type and, more importantly, mismatches plural new with singular delete. I need it to delete in a special way.
Is there a way to easily set that up without defining an outside function? Perhaps by having the shared pointer call Thing::destroy() when the ref count empties? I know that shared pointer can accept a "deleter" as a template argument, but I'm unsure how to use it, or if it's even the proper way to address this?
std::shared_ptr accepts a deleter function as a second parameter, so you can use that to define how the managed object will be destroyed.
Here's a simplified example:
class Thing
{
public:
~Thing()
{
std::cout << "~Thing\n";
}
static std::shared_ptr<Thing> create() {
char * data = new char[sizeof(Thing)];
Thing* thing = new (data) Thing{};
return std::shared_ptr<Thing>{thing, &Thing::destroy};
}
static void destroy(Thing* p) {
p->~Thing();
delete [] (char*)p;
}
};
int main()
{
auto p = Thing::create();
}
Live Demo
I have 10 char* properties of my class called Car,what is the best way to write the setters of these 10 char* properties? One way is to directly set the value in it :
void Car<T>::setKey(const char* toCopyKey)
{
delete[] key;
int length=strlen(toCopyKey);
key=new char[length+1];
strcpy(key,toCopyKey);
}
and do this 10 times ,other solution I thought of , is to make a function that creates a copy of the passed char* and then assigns it in the setter :
char* Car<T>::copyString(const char* s)
{
int length=strlen(s);
char* property=new char[length+1];
strcpy(property,s);
return property;
}
and use the copyString method in every setter like this :
void Car<T>::setModel(const char* toCopyModel)
{
delete[] model;
model=copyString(toCopyModel);
}
But I was wondering if this second solution is correct and if there is a better way to do this copying?I cannot use std::string and vector.
I guess this is an assignment of some C++ course or tutorial, because otherwise I would recommend to question the whole design.
In general, I would learn as early as possible to not do manual memory management at all and use C++ standard library smart pointers. This relieves you from the burden to write destructors, copy|move-assignment and copy|move constructors.
In your example, you could use std::unique_ptr<char[]> to hold the string data. This is also exception safe and prevents memory leaks. Creation of the unique_ptr<char[]> objects can be centralized in a helper method.
class Car {
private:
std::unique_ptr<char[]> model;
std::unique_ptr<char[]> key;
static std::unique_ptr<char[]> copyString(char const* prop) {
auto const len = std::strlen(prop);
auto p = std::make_unique<char[]>(len+1);
std::copy(prop, prop + len, p.get());
p[len] = '\0';
return p;
}
public:
void setModel(char const* newModel) {
model = copyString(newModel);
}
void setKey(char const* k) {
key = copyString(k);
}
char const* getModel() const {
return model.get();
}
};
If you don't know them, I would recommend to read about the rule of zero.
You can combine your two methods by using a reference parameter:
static void Car<T>::setStringProp(char *&prop, const char *toCopyString) {
delete[] prop;
prop = new char[strlen(toCopyString)+1];
strcpy(prop, toCopyString);
}
void Car<T>::setModel(const char *toCopyModel) {
setStringProp(model, toCopyModel);
}
And make sure that your constructor initializes all the properties to NULL before calling the setters, because delete[] prop requires that it be an initialized pointer.
Car<T>::Car<T>(const char *model, const char *key, ...): model(nullptr), key(nullptr), ... {
setModel(model);
setKey(key);
...
}
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));
I have used pointers to create an array and then wrote a delete procedure in the destructor
class cBuffer{
private:
struct entry {
uint64_t key;
uint64_t pc;
};
entry *en;
public:
cBuffer(int a, int b, int mode)
{
limit = a;
dist = b;
md = mode;
en = new entry[ limit ];
for (int i=0; i<limit; i++) {
en[i].key = 0;
en[i].pc = 0;
}
};
~cBuffer() { delete [] en; }
...
}
In another class I use cBuffer like this:
class foo() {
cBuffer *buf;
foo()
{
buf = new cBuffer(gSize, oDist, Mode);
}
};
However, valgrind complains about the new operator
==20381== 16,906,240 bytes in 32 blocks are possibly lost in loss record 11,217 of 11,221
==20381== at 0x4A0674C: operator new[](unsigned long) (vg_replace_malloc.c:305)
==20381== by 0x166D92F8: cBuffer::cBuffer(int, int, int)
cBuffer *buf;
foo()
{
buf = new cBuffer(gSize, oDist, Mode);
}
You need to call
delete buf;
Since you explicitly called new
Your class foo will cause your leak, since you never delete the dynamically allocated cBuffer. The solution is simple: there's no need for dynamic allocation at all here.
class foo {
cBuffer buf; // An object, not a pointer
foo() : buf(gSize, oDist, Mode) {}
};
More generally, when you do need dynamic allocation, be careful that you always delete what you new. The most reliable way to do this is to use RAII types such as containers and smart pointers to manage all dynamic resources for you.
I should get the same in both lines..
what happen I get two different values.. like it was aiming to different positions..
I think the error is inside the d->add(*b)
the output is
thiago 14333804
Ph¿├┌ 2816532
to describe it better I put the code below
I got a program
int main(int argc, char **argv) {
CClass* c = new CClass();
BClass* b = c->getNext();
printf("%s %d \n", b->getValue(), b->getValue());
DClass* d = new DClass();
d->add(*b);
printf("%s %d \n", d->getNext(), d->getNext());
cin.get();
return 0;
}
the interfaces are below
class BClass
{
private:
char* value;
bool stale;
public:
BClass(char* value);
~BClass(void);
char* getValue();
bool isStale();
};
class CClass
{
private:
vector<BClass*> list;
public:
CClass(void);
~CClass(void);
BClass* getNext();
};
class DClass
{
private:
vector<BClass*> list;
static bool isStale(BClass* b) { return b->isStale();};
public:
DClass(void);
~DClass(void);
void add(BClass s);
char* getNext();
};
and the implementation follows
//BClass
BClass::BClass(char* value)
{
this->value = value;
this->stale = false;
}
BClass::~BClass(void)
{
}
char* BClass::getValue()
{
return value;
}
bool BClass::isStale()
{
return stale;
}
//CClass
CClass::CClass(void)
{
list.push_back(new BClass("thiago"));
list.push_back(new BClass("bruno"));
list.push_back(new BClass("carlos"));
}
CClass::~CClass(void)
{
}
BClass* CClass::getNext()
{
return list.at(0);
}
//DClass
DClass::DClass(void)
{
}
DClass::~DClass(void)
{
}
void DClass::add( BClass s )
{
list.push_back(&s);
}
char* DClass::getNext()
{
BClass* b = list.at(0);
return b->getValue();
}
When you pass in an instance of class B into D::add() function you create a deep copy of the object and that copy is what is put on stack. Later on you use the address of that copy to push it into list. Once the function is done this automatic variable goes out of scope thus the pointer you used to put into list is no longer valid.
To fix change your interface to avoid deep copies as follows:
void DClass::add( BClass * s )
{
list.push_back(s);
}
Step-by-step of what your code is doing
BClass* b = c->getNext(); // you get the address of the first element from the list (created in constructor) and assign it to b
d->add(*b); // the *b will dereference the object pointed to by b and put it onto stack in preparation to the call to add()
void DClass::add( BClass s ){ // the deep copy of a dereferenced object is put into this function's stack frame
list.push_back(&s); // an address of that temporary copy of the original object is being used to be added to your list
} // this is where the fun happens - once the function is done it will unwind the stack back up and the memory, previously occupied by that temp copy, will be re-used for other purposes. In your case - it will be used to pass parameters to functions d->getNext() (there's always a hidden this parameter to non-static member functions) and later to the printf() function. Remember - your previous pointer to that temp copy is still pointing to the stack, but it's now occupied by different data, causing you to see corruption
General rule of thumb - never use pointers to temp objects ;-)
in the DClass::add function, BClass s is a local variable.
void DClass::add( BClass s )
{
list.push_back(&s);
}
When you call d->add(*b);, you're passing a BClass by value, meaning you're creating a copy of it, and the address of that copy is not the same address of the original.
s will go out of scope as soon as the function returns, and the pointer to it will be invalid. So storing that pointer is no good to you, since dereferencing it would be undefined behaviour.