So I've been working on memory management and have a particular issue when it comes to moving objects that contain function objects that wrap lambda's that capture data. Suppose the following example:
typedef std::function < void( int ) > funcType;
class Something
{
private:
int _myNum = 0;
public:
funcType GetSetIt( )
{
return [&] ( int a )
{
_myNum = a;
};
}
void SeeIt( )
{
std::cout << _myNum << std::endl;
}
int GetIt( )
{
return _myNum;
}
};
And the following operations:
auto destination = ( Something* ) malloc( sizeof( Something ) );
auto alt = ( funcType* ) malloc( sizeof( funcType ) );
auto size = sizeof( funcType );
auto s = new Something( );
auto setIt = s->GetSetIt( );
setIt( 10 );
s->SeeIt( );
auto a = s->GetIt( );
memcpy( destination, s, sizeof( Something ) );
memset(s, 0, sizeof( Something ) );
memcpy( alt, &setIt, sizeof( funcType ) );
memset( &setIt, 0, sizeof( funcType ) ); // point 1
(*alt)( 15 );
destination->SeeIt( );
auto b = destination->GetIt( );
A quick explanation:
Create a new Something and call all of it's members to make sure it's working correctly. Then move it to a new location and delete/clear where it used to exist. Also move the function object to a new location and clean up after. Then, using pointer's to the new locations, call the function object and the methods on the object.
The first issue is that everything is moving along smoothly until I memset the original location of the function object. If you comment out that line (noted with // point 1) you'll notice it does not crash.
This is a little strange to me, but I don't fully understand how function objects are laid out in memory and was hoping for a little light to be shed in that area. I would assume that if I block-copied the entire object to another area and cleared the old space (not deleting it because it's on the stack) that it and all of it's references would be preserved.
The second issue, assuming you've commented out the memset line is that "expected results" are not the same as "desired results". I expect that calling alt will set _myNum on s to 15, and it does. But I want to update alt's pointer to Something (which I usually refer to as it's this pointer) to point to destination. How can I achieve that? Can it be done dependably across compilers? I've been worried that, although I could conceivably find where it's stored and update the value, the solution won't be solid because lambda's can be implemented in a variety of ways across compilers and there may be some "magic" at hand.
Any help or insight into these issues is greatly appreciated. If I'm not clear on what's going on, comment and I'll provide more detail where needed. Thanks in advance!
function is not trivially copyable (3.9p9, 9p6) so you cannot copy it with memcpy. Use the is_trivially_copyable trait to detect whether a type is trivially copyable.
If you want to "move" an object of a non-trivially copyable type from one location to another, use placement new with its move constructor and perform a destructor call on the previous location:
new (*buf) T(std::move(obj));
obj.~T();
You should use placement new and ensure the setter is taken from the copied object:
#include <functional>
#include <iostream>
// ...
int main() {
char source[sizeof(Something)];
char source_setter[sizeof(funcType)];
Something* src = new (source) Something;
// Get the setter from the source object.
funcType* src_setter = new (source_setter) funcType(src->GetSetIt());
(*src_setter)(0);
char destination[sizeof(Something)];
char destination_setter[sizeof(funcType)];
Something* dst = new (destination) Something(*src);
// Get the setter from the destination object.
funcType* dst_setter = new (destination_setter) funcType(dst->GetSetIt());
(*dst_setter)(1);
src->SeeIt();
dst->SeeIt();
src_setter->~funcType();
src->~Something();
dst_setter->~funcType();
dst->~Something();
}
Related
I have a method with the prototype:
bool getAssignment(const Query& query, Assignment *&result);
I am a bit confused about the type of the second param (Assignment *&result) since I don't think I have seen something like that before. It is used like:
Assignment *a;
if (!getAssignment(query, a))
return false;
Is it a reference to a pointer or the other way around ? or neither ? Any explanation is appreciated. Thanks.
It's a reference to a pointer. The idea is to be able to change the pointer. It's like any other type.
Detailed explanation and example:
void f( char* p )
{
p = new char[ 100 ];
}
int main()
{
char* p_main = NULL;
f( p_main );
return 0;
}
will not change p_main to point to the allocated char array (it's a definite memory leak). This is because you copy the pointer, it's passed by value (it's like passing an int by value; for example void f( int x ) != void f( int& x ) ) .
So, if you change f:
void f( char*& p )
now, this will pass p_main by reference and will change it. Thus, this is not a memory leak and after the execution of f, p_main will correctly point to the allocated memory.
P.S. The same can be done, by using double pointer (as, for example, C does not have references):
void f( char** p )
{
*p = new char[ 100 ];
}
int main()
{
char* p_main = NULL;
f( &p_main );
return 0;
}
For something like this, you basically read the declaration from right to left (or inside out).
In other words, you want to start from the name of the item being declared, then progress outward. In this case, progressing directly from the name to the type, we get:
I'm quite new to smart pointers and was trying to refactor some existing code to use auto_ptr. The question I have is about double pointers and their auto_ptr equivalent, if that makes sense.
I have a function that accepts a double pointer as its parameter and the function allocates resources for it:
void foo ( Image** img ) { ... *img = new Image(); ...}
This function is then used like this:
Image* img = NULL;
foo ( &img );
...
delete img;
I want to use auto_ptr to avoid having to call delete explicitly. Is the following correct?
void foo ( auto_ptr<Image>* img ) { ... *img = auto_ptr<Image>(new Image()); ...}
and then
auto_ptr<Image> img = NULL;
foo ( &img );
Thanks.
std::auto_ptr<> has weird copy semantics (actually it's move semantics, rather than copy semantics) and is often not what you want when you want a smart pointer. For example, it cannot be put into STL containers.
If your standard library comes with TR1 support, use std::tr1::shared_ptr<> instead. (If it doesn't, use boost's boost::shared_ptr<>, which is what std::tr1::shared_ptr<> was taken from.)
If you want to stick with std::auto_ptr<> for your code, you can pass it into the function per non-const reference:
void foo ( std::auto_ptr<Image>& img ) { ... img.reset(new Image();) ...}
std::auto_ptr<Image> img;
foo ( img );
...
// no need to delete
Or you could just return the pointer:
std::auto_ptr<Image> foo () {return std::auto_ptr<Image> img(new Image();)}
It depends on whether or not your STL's implementaton of auto_ptr overrides the '&' operator to return a pointer-to-pointer (most smart pointer classes tend to, but not all auto_ptr implementations do).
If you really want to re-write your code to pass auto_ptr objects around, then you should do something more like this instead, which would be safer:
void foo ( std::auto_ptr<Image> &img ) { ... img.reset(new Image()); ...}
std::auto_ptr<Image> img;
foo ( img );
Since you are refactoring, I would go one step further and convert the parameter into a return value:
// void foo( Image ** img )
std::auto_ptr<Image> foo() {
std::auto_ptr<Image> tmp( new Image() );
// ...
return tmp;
}
Even if I prefer removing the requirement from the interface (so that the caller can decide to change the code to use any other type of smart pointer at will):
Image* foo() {
std::auto_ptr<Image> tmp( new Image() );
// ...
return tmp.release();
}
int main() {
std::auto_ptr<Image> ptr( foo() );
}
Just when I thought I had it figured out, I get an exception handling error. Problem: The problem is that the private members lose the information outside of the constructor. Here's my class definition
Code:
class ClassType
{
private:
char *cPointer;
int length;
public:
ClassType();
// default constr. needed when allocating in main.
ClassType( const ClassType* );
char otherFunc();
};
classtype.cpp:
"#include ClassType.h"
ClassType( const ClassType* )
{
cPointer = ClassType->cPointer;
length = ClassType->length;
}
ClassType::ClassType( const char *myVar )
{
cPointer = new char[ strlen( myVar ) + 1 ] //+1 for trailing '\0'
strcpy( cPointer, myVar );
length = strlen( cPointer );
}
char ClassType::otherFunc()
{
cPointer; // Nothing is shown when debugging..
cPointer = "MyPointer"; // Results in acrash
length = 5; // Results in a crash
}
// The main function is working properly.
This isn't valid C++ code.
If you are using C++, shouldn't you
use std::string for the string?
Constructor based on another
instance should be ClassType(const
ClassType& rhs)
I can't think of why it would crash where you indicate, but there are several problems with your code (some of which are compile-time problems, so we can't be sure this code accurately reflects the problem):
there are ownership problems - when ClassType::ClassType( const ClassType* ) is called, which instance of ClassType owns the object pointed to by cPointer?
there's no dtor to release the memory allocated in `ClassType::ClassType( const char *myVar )'
since cPointer may point to something allocated by new or might not, you'll have issues trying to determine when the thing allocated by new should be deleted.
As far as the compile time errors go:
the definition of ClassType( const ClassType* ) should start with ClassType::ClassType( const ClassType* )
the contents of ClassType::ClassType( const ClassType* ) should be using a parameter instead of the ClassType class name as the pointer
char ClassType::otherFunc() needs a return statement
Is this the real code?
ClassType( const ClassType* )
{
cPointer = ClassType->cPointer;
length = ClassType->length;
}
If so, it needs to be like this:
ClassType( const ClassType* rhs )
{
cPointer = rhs->cPointer;
length = rhs->length;
}
Also, this constructor is not the default ctor:
ClassType( const ClassType* ); // default constr. needed when allocating in main.
A default ctor is specifically a ctor that either takes zero parameters or all the parameters have defaults specified. In other words, a default ctor is a ctor that can be called like this:
ClassType myObject;
I provided a pretty complete answer in your other question about this code. I believe that the main issue is that your copy constructor is massively broken. It will cause double free errors and other badness. Also since your destructor calls delete on the pointers you allocate, you can't ever assign string literals to your classes pointers.
Default constructors are those for which all the arguments have default values, so your constructor that takes a pointer is not a default constructor.
Your crash locations indicate the class has not been constructed properly, so you're probably getting address errors when you assign to them.
Could you post main, as that is probably key to see the problem?
I need to call my public member. The Constructor that takes 1 paramater.
This is how my code looks:
// main
char tmpArray[100] = {};
while ( !inFile.eof() )
{
for ( unsigned x = 0; x < str2.length(); x++ )
{
if ( !isspace( str2[x] ) || isspace( str2[x] ) )
{
tmpArray[x] = str2[x]; // prepare to supply the constructor with each word
ClassObject[wrdCount] = new ClassType[x] ;
//ClassObject[wordCount]->ClassType( tmpArray );
}
}
}
The error is:
'function-style cast' : illegal as
right side of '->' operator
To try and resolve the issue i try two equivalent expressions:
/* no good */ (*ClassObject[wrdCount]).ClassType( tmpArray );
/* no good */ (*ClassObject[wrdCount][10]).ClassType( tmpArray );
/* combine */ ClassObject[arbitrary][values]->ClassType( tmpArray );
Intellisense does brings up all my members and privates except the constructor..
Could this be the reason?
//MyHeader.h
class ClassObject
{
private:
const char* cPtr;
float theLength;
public:
ClassObject( const char* ); // Yes its here and saved..
ClassObject(); // an appropriate default constructor
~ClassObject( );
char GetThis( );
char* GetThat( );
}
I am assuming the following things as it is not clear from the code posted:
(1). ClassObject is defined like this: ClassType* ClassObject[/some value/10];
(2). The class definition in MyHeader.h is of ClassType and not of ClassObject.
In such a case, the following statement is the problem:
ClassObject[wrdCount] = new ClassType[x]
Here it creates 'x' number of ClassType objects. I don't think thats what you want. I guess you want to construct a ClassType object by passing const char* as the constructor parameter. If that is so you should use it like this:
ClassObject[wrdCount] = new ClassType(tmpAray);
Also note that you are assuming size of the array passed. I suggest it is better to use something like a std::string instead of raw character arrays.
I'm not entirely clear on what you're doing, but you cannot explicitly call a constructor like that. If you have a pointer-to-a-pointer-to-a-ClassType called ClassObject, you need to do something like this to initialize it:
ClassObject[wrdCount] = new ClassType*[x]; // create a new 'row' in the array with x columns
for (int i = 0; i < x; ++i) // initialize each 'column' in the new row
ClassObject[wrdCount][i] = new ClassType(tmpArray);
This doesn't seem to make much sense given the code you have pasted though (since wrdCount doesn't change). It's hard to say without an exact problem description.
You need to use identifiers. The following:
ClassObject[wrdCount] = new ClassType[x] ;
tries to apply the operator[] to a class type name. What good can that do? None. Try:
ClassObject *a = new ClassType[x];
This'd create an object a of type array of size x of Classtypes. Do you need an array here -- it's upto you. If all you need is a single variable use:
ClassObject *a = new ClassType;
Is it possible to declare a variable in c++ without instantiating it? I want to do something like this:
Animal a;
if( happyDay() )
a( "puppies" ); //constructor call
else
a( "toads" );
Basially, I just want to declare a outside of the conditional so it gets the right scope.
Is there any way to do this without using pointers and allocating a on the heap? Maybe something clever with references?
You can't use references here, since as soon as you'd get out of the scope, the reference would point to a object that would be deleted.
Really, you have two choices here:
1- Go with pointers:
Animal* a;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
// ...
delete a;
or with a smart pointer
#include <memory>
std::unique_ptr<Animal> a;
if( happyDay() )
a = std::make_unique<Animal>( "puppies" );
else
a = std::make_unique<Animal>( "toads" );
2- Add an Init method to Animal:
class Animal
{
public:
Animal(){}
void Init( const std::string& type )
{
m_type = type;
}
private:
std:string m_type;
};
Animal a;
if( happyDay() )
a.Init( "puppies" );
else
a.Init( "toads" );
I'd personally go with option 2.
You can't declare a variable without calling a constructor. However, in your example you could do the following:
Animal a(happyDay() ? "puppies" : "toads");
You can't do this directly in C++ since the object is constructed when you define it with the default constructor.
You could, however, run a parameterized constructor to begin with:
Animal a(getAppropriateString());
Or you could actually use something like the ?: operator to determine the correct string.
(Update: #Greg gave the syntax for this. See that answer)
I prefer Greg's answer, but you could also do this:
char *AnimalType;
if( happyDay() )
AnimalType = "puppies";
else
AnimalType = "toads";
Animal a(AnimalType);
I suggest this because I've worked places where the conditional operator was forbidden. (Sigh!) Also, this can be expanded beyond two alternatives very easily.
If you want to avoid garbage collection - you could use a smart pointer.
auto_ptr<Animal> p_a;
if ( happyDay() )
p_a.reset(new Animal( "puppies" ) );
else
p_a.reset(new Animal( "toads" ) );
// do stuff with p_a-> whatever. When p_a goes out of scope, it's deleted.
If you still want to use the . syntax instead of ->, you can do this after the code above:
Animal& a = *p_a;
// do stuff with a. whatever
In addition to Greg Hewgill's answer, there are a few other options:
Lift out the main body of the code into a function:
void body(Animal & a) {
...
}
if( happyDay() ) {
Animal a("puppies");
body( a );
} else {
Animal a("toad");
body( a );
}
(Ab)Use placement new:
struct AnimalDtor {
void *m_a;
AnimalDtor(void *a) : m_a(a) {}
~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); }
};
char animal_buf[sizeof(Animal)]; // still stack allocated
if( happyDay() )
new (animal_buf) Animal("puppies");
else
new (animal_buf) Animal("toad");
AnimalDtor dtor(animal_buf); // make sure the dtor still gets called
Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf));
... // carry on
Since c++17, there is now an overhead-free way to do this: std::optional. The code in this case would be:
#include <optional>
std::optional<Animal> a;
if (happyDay()) {
a.emplace("puppies");
} else {
a.emplace("toads");
}
The best work around is to use pointer.
Animal a*;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
You can also use std::move:
class Ball {
private:
// This is initialized, but not as needed
sf::Sprite ball;
public:
Ball() {
texture.loadFromFile("ball.png");
// This is a local object, not the same as the class member.
sf::Sprite ball2(texture);
// move it
this->ball=std::move(ball2);
}
...
There is a way to do this without pointers/heap memory, this syntax is just a bit gibberish. Here is an example using std::string. I don't recommend doing this unless you really need the performance.
uint8_t object[sizeof(std::string)];
int main() {
if(true)
new(&object) std::string("Your arguments");
else
new(&object) std::string("Your other arguments");
(*(std::string*)(&object)).append("");
std::cout << (*(std::string*)(&object));
return 0;
}
The annoying part about this is you have to cast object to a string every time you want to use it:
(*(std::string*)(&object))
Yes, you can do do the following:
Animal a;
if( happyDay() )
a = Animal( "puppies" );
else
a = Animal( "toads" );
That will call the constructors properly.
EDIT: Forgot one thing...
When declaring a, you'll have to call a constructor still, whether it be a constructor that does nothing, or still initializes the values to whatever. This method therefore creates two objects, one at initialization and the one inside the if statement.
A better way would be to create an init() function of the class, such as:
Animal a;
if( happyDay() )
a.init( "puppies" );
else
a.init( "toads" );
This way would be more efficient.