I have a class with a static member that's a pointer like so :
animation.h
class Animation
{
public:
Animation();
static QString *m;
};
animation.cpp
#include "animation.h"
QString* Animation::m = 0;
Animation::Animation()
{
}
When I try to initialize that 'm' pointer from another class like so :
Animation::m = new QString("testing");
It works.
But when I do it this way :
QString x("Testing");
Animation::m = &x;
The program crashes.
What is wrong with this second method ?
Also I would like to have that static pointer as private so I can make static getter and setter functions to it. The setter should use the second method as the 'x' will come in a parameter so I'm stuck.
Thanks for any help!
I bet it's not crashing on that line, but afterwards.
The problem is that you're taking the address of a variable located in automatic memory, and probably try to access it afterwards. The variable x will be destroyed when it's scope ends, but Animation::m will still point to that memory (memory you no longer own after x went out of scope). This results in undefined behavior.
Just like the following would be illegal:
int* x = NULL;
{
int k = 3;
x = &k;
}
*x = 4;
Workaround assign to the value, not the pointer (provided it was previously assigned to a valid QString*):
QString x("Testing");
*(Animation::m) = x;
What is wrong with this second method ?
It crashes because you most likely access it beyond the scope in which x was created.
Automatic variables are automatically destroyed once the control exits the scope { } in which they were created, So beyond the scope what you have is an pointer pointing to data that does not exist. Accessing this data causes an Undefined Behavior and a crash.
How to go about it?
You should dynamically allocate memory and then copy the string to the dynamically allocated pointer so that you are able to access it everywhere. This way the string remains valid unless and untill explicitly deleteed.
I'll bet that your program crashes when you use Animation::m after x has been destroyed (probably by going out of scope).
If you want to use a setter to assign to Animation::m, you'll need to pass in the argument as a pointer or by reference:
class Animation
{
public:
Animation();
void set_m( QString* ptr) {
m = ptr;
}
void set_m( QString& ref) {
m = &ref;
}
private:
static QString *m;
};
However, you'll still need to make sure that whatever m points still is still alive when you try to use m.
Related
Summarizing:
Is it possible to change a class member property memory address?
What lead me to do this question:
I'm not sure if what I want to do will lead into my expected behavior, and even if it works as expected, if it is what I should do.
So, I have a member property which I want to read from disk, say for instance that it is prop from MyClass. The routine I have that read the property from disk getVarOnFile I do not have access to the implementation, but it uses a pointer to the type to fill the value on the file.
In the documentation it says that if the property does not exists, the pointer may be null, although I am unsure if it will set it to null or it is because it expects that I enter null pointer to the function.
Because of that, instead of using the destVar pointer itself, I use a localVar pointer, and then set the destVar to localVar.
But I am not sure if I should do that, it seems that this will segment memory, where most of the members are close in the memory, but not this one that I set to the memory place reserved by the file.
void readHelper(const char* propOnFile, float*& destVar)
{
// check if propOnFile exists
float *localVar = nullptr;
getFileOnVar(propOnFile,localVar);
if ( localVar != nullptr){
destVar
}
}
class MyClass {
private:
float prop;
public:
static MyClass *read(const char* file){
readHelper("prop",&(this->prop));
}
};
I am not sure what would happen to the original memory place reserved for the original class property member, which was replaced to a new place. It will be freed or this would be memory leak?
Changing class member address
If I understand your question correctly, that is not possible.
Say you have:
struct Foo
{
int a;
};
Foo f;
Once you have created f, the address of f and f.a are not changeable. You can only modify their values.
My code:
#include<iostream>
using namespace std;
struct element
{
int liczba;
element *nastepny;
element();
};
element::element()
{
nastepny=0;
}
int main()
{
element pierwszy;
pierwszy.liczba=1;
element drugi;
(*nastepny).pierwszy=2;
drugi.liczba=2;
return 0;
}
It says that *nastepny was not declared, but I do not know how is it possible. I created structure with *nastepny. If I write element *nastepny, it says that element has no member named pierwszy. SOmething is going wrong because pierwszy is declared at the beginning of main function.
(*nastepny).pierwszy=2;
That makes no sense as nastepny is not declared statically or within its current or any parent scope. It is a member of your structure and only exists as a part of and instance of one.
Also, you cannot simply assign two to the address of some unallocated pointer. You have a pointer, but it does not yet point anywhere valid. So, either:
drugi.nastepny = malloc(sizeof *drugi.nastepny);
*drugi.nastepny = whatever;
To allocate space dynamically, or...
drugi.nastepny = &some_variable;
But watch for lifetime issues on that last one.
The error happens in
(*nastepny).pierwszy=2;
^^^^^^^^
nastepny is not declared in this scope. The member of the struct doesn't make it accessible outside the struct (instances).
I guess you are meaning something like this:
drugi.nastepny = &pierwszy;
drugi.nastepny->liczba = 2;
I auggest this:
pierwszy.nastepny = &drugi;
I'm not sure how you expect to get an object when you deference your pointer when you never assigned it a memory address?
If you want to get a pointer to the object itself then you can use the this pointer. However in this scenario such an application of it would make no sense.
The only assignment you provided to the element pointer was 0 (NULL), so it's not pointing to any element object.
I read that it is good practice to do a check in the destructors of classes after deletion for pointer data members as follows:
if( 0 != m_pPointer)
{
delete m_pPointer;
m_pPointer= 0;
}
However, I found out that this prevents you to declare const pointers as data members as follows:
Type* const m_pPointer;
Isn't assigning NULL to pointers(as in my example above) a barrier for const-correctness?
What is the best way to do? Keep everything const and stop assigning NULL to the deleted pointer or declaring non-const pointers even though their address never changes?
This is bad practice for the following reasons:
Setting a pointer to null in the destructor may mask double destruction problem. Good practise is to detect problems as early as possible.
Checking a pointer for null before deleteing it only adds unnecessary code. delete handles null pointers by doing nothing. Good practice is to minimize the amount of code.
Deleting a null pointer is guaranteed safe, so that null check is pointless.
If a class has a member that is a const pointer to a non-const object then you're saying the pointer value WILL NOT change within the lifetime of the wrapping object - that being the case you should only do this in the case where the object pointed to will live as long or longer than the wrapping object and the wrapping object will never want to point to a different object.
The fact that you have this issue simply means you've used a const pointer in the wrong place. You claim that in your case the pointer value never changes, but in your example it obviously does - it changes to null.
The "best way to do" is:
class foo {
std::unique_ptr<bar> m_pPointer;
public:
foo(std::unique_ptr<bar> pPointer)
: m_pPointer{std::move(pPointer)} {}
};
or for const,
class foo {
const std::unique_ptr<bar> m_pPointer;
public:
foo(std::unique_ptr<bar> pPointer)
: m_pPointer{std::move(pPointer)} {}
};
No new, no delete, no destructor.
A weird situation can be caused when you link a static lib with a global or static object from two different shared libs (on Linux) which later be linked to the same executable.
Each shared lib object insert call to constructor and destructor, so you'll have one object and two calls for constructor and destructor for the same object (actually you'll have 2 objects mapped to the same address).
You'll probably find the problem when your app crash in the 2nd destructor.
if you NULL it you'll never know that there was a problem at all.
for your question: except for the above issue, I think you should distinct two types of pointers:
See the class below:
class A{
obj *x, *y;
A(){
x = new obj;
y = NULL
}
~A(){
delete x;
if(y)delete y; // the `if` here will save the calling and returning run time when NULL.
}
void RecicleX(){
delete x;
x = new obj;
}
void InitY(){
assert(y==NULL); //illegal to call init when already
y = new obj;
}
void TermY(){
assert(y); //illegal to call term when already inited
delete y;
y = NULL; //prevent crush in dtor if called after...
}
};
x is always exists, so no need to check it, and no need to null it. y may exists and may not, so I think you should null it after deletion.
(You maybe will want also to know the current state, like for assert)
I use boost shared_ptr to wrap a pointer. However I can only get the correct value in test_shared_ptr(), while in main(), I get the wrong value.
Expected output:
100
100
Actual output:
100
-572662307
It seems that the pointer becomes invalid in that case. Any correct approach to do the job? Thanks in advance.
Below is the source code.
#include <memory>
#include <iostream>
class TestClass
{
public:
TestClass(int &i);
void print_i();
private:
int *_i;
};
TestClass::TestClass(int &i) : _i(&i)
{
}
void TestClass::print_i()
{
std::cout << *_i << std::endl;
}
void print_i(int &i)
{
std::cout << i << std::endl;
}
TestClass *test_shared_ptr()
{
std::tr1::shared_ptr<int> i(new int());
*i = 100;
print_i(*i);
return new TestClass(*i);
}
int main(int argc, char** argv)
{
TestClass *p = test_shared_ptr();
p->print_i();
return 0;
}
You need to pass around the shared pointer, rather than references and pointers directly to the int.
What's happening is the shared pointer is never passed anywhere outside the test_shared_ptr() function. When that function returns, the shared pointer is destroyed. When it sees that nothing else has a reference to it's memory, it destroys the memory it was pointing at.
Basically, where you are using int &i and int *i change both to use std::tr1::shared_ptr<int> i.
You probably need to read up on shared pointer a bit more. Basically, they keep a reference count for the pointer they are pointing to. When they are copied, they up the reference count, and when they are destroyed the decrement it. When the reference count reaches 0 (nothing else is referencing the memory it is pointing at) it frees that memory. So, even though something is using that pointer in your case, because it did not use a shared pointer there is no way for the shared pointer to know that the memory is still being used, so it frees it.
It seems that the pointer becomes invalid in that case
Of course it becomes invalid. shared_ptr gets deleted when you leave test_shared_ptr, and i does not exist after that.
Any correct approach to do the job?
1) simply copy value of i. (use int i instead of int* i in TestClass). int is small, you won't lose anything.
or
2) use std::tr1::shared_ptr<int> instead of int* in TestClass.
The issue you are having is with your API contract.
I don't want to use shared pointer to pass variable values in TestClass's constructor, since I don't want to force the api user to use smart pointer
Your TestClass contract is currently looking like you want the caller to maintain the int item so that it has a lifetime longer than TestClass.
Your test case doesn't follow this contract rule however.
Actually I want to pass object by reference instead of generic type in my application.
Passing by reference or by pointer does not have anything to do with 'generic' type.
Here is a possible fix for your code testing your API, the scope of your int is then longer then sufficiently long (untill the end of the app) to handle all usages within TestClass
TestClass *test_shared_ptr(int &i)
{
i = 100;
print_i(i);
return new TestClass(i);
}
int main(int argc, char** argv)
{
std::tr1::shared_ptr<int> i(new int());
TestClass *p = test_shared_ptr(*i);
p->print_i();
return 0;
}
What you are doing really breaks the point of shared_ptr. Basically when you pass it out of that function is it magically supposed to break and, thus, not free the pointed too memory?
No. It frees it. Are you expecting the shared_ptr to still exist outside of the function so that when "p" drops out of scope it manages to call teh shared_ptr destructor? This can't happen. p is a pointer not a shared_ptr class.
Either return a shared_ptr or return the new'd pointer and delete it yourself.
This problem involved me not knowing enough of C++. I am trying to access a specific value that I had placed in the Heap, but I'm unsure of how to access it. In my problem, I had placed a value in a heap from a data member function in an object, and I am trying to access it in another data member function. Problem is I do not know how, and I had searched examples online, but none were what I needed as they were all in int main() and were not specifically what I needed.
In the first data member function, I declare the value I want to be sent to the Heap;
Here's an example of what my first data member function.
void Grid::HeapValues()
{
//Initializing Variable
value = 2; //The type is already declared
//Pointers point a type towards the Heap
int* pValue = new int;
//Initialize an a value of in the Heap
*pValue = value;
}
And in data member function This is what want:
void Grid::AccessHeap()
{
//Extracting heap:
int heap_value = *pValue; //*pValue does not exist in this function
cout << heap_value; //Delays the value 2, which is found
//in the first data member function
}
I feel foolish for asking, but I am unable to find the answers and do not how. Does anyone know how to access a value from the heap in a simple way? And I would need it to be able to access in more then two data member function.
pValue needs to be a member-variable of the class Grid.
class Grid
{
private: int* pValue;
public: void HeapValues();
void AccessHeap();
};
Now the member-variable pValue is accessible from any member-function of Grid.
Don't forget to delete your pointer in the destructor when you are done. For more information visit:
http://www.cplusplus.com/doc/tutorial/variables.html <-- Variable scope
http://www.cplusplus.com/doc/tutorial/pointers.html <-- Pointers
http://www.cplusplus.com/doc/tutorial/dynamic.html <-- Dynamic memory
Like Aaron said you can make the value a member of your Grid class. In this case though there is no need for it to be a pointer to an int.
class Grid
{
private:
int value;
public:
void HeapValue();
void AccessHeap();
};
The value will be stored as part of the object wherever it is instanciated. You can make it on the stack or the heap, it doesn't matter. For simple values like the built in types and Objects that will be owned by the instance of the class it is unnecessary to allocate them using new. This way you don't need to worry about cleaning up with the delete operator in the Grid destructor, just make sure you dispose of the owning Grid instance properly ;-)
Of coarse there are exceptions to this that you will learn as you delve more into C++, but for your example the above will be fine.
Why do you want it on the heap? If you add it as part of the class then it will be in the same place the class is, possibly on the stack or in global memory. Perhaps you want to have a variable size to your integer pointer? In that case, then you need to be sure to deallocate the memory when you are done with it.
The problem with stuff on the heap is finding it. There is no accessing it by name, unless you add a mechanism for that. Somehow you need to communicate the location to whatever code needs to access it. In this case, it looks like you only need access within the Grid class, so it is easy. Just make it a member variable like Aaron indicates. You might end up with something like:
class Grid
{
protected:
int* pVals;
public:
Grid() pVals(NULL) { }
~Grid() { delete [] pVals; }
void HeapValues() {
pVals = new int[getHeapValuesSize()];
pVals[0] = 1; // ...
}
void AccessHeap() {
cout << pVals[0]; // ...
}
(On a side note, you appear to be using the phrase "data member function" when you mean "member function". "Data member" refers to member data of a class, like pVals, but I'm not sure what "data member function" would mean.)