Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
EDIT I don't need a solution to a problem, I want to know if and why I should prefer one thing over another. The function declaration can not change.
I have a C++ project and I need to write some code that will be called by code written in C. I have a class called A, and I need to implement a method that destroys such an object that was allocated by new, and nullify the pointer itself.
The declaration looks like this:
void destroy_A(void** a);
I need a void** so I can nullify *a.
Which of the following should I use (if any), and why?
delete *(A**)a;
delete *((A**)a);
delete (A*)*a;
EDIT: Maybe I wasn't clear: I don't know the technical terms, but I do use delete and not free, and the actual methods are called via code compiled in C. Otherwise, I wouldn't need the void**.
This is my CS faculty requirements, I didn't write the assignment :)
All three of them work. What you are looking for, in the end is
A* somePtr = ...; // get a pointer to your object
delete somePtr; // delete the object it points to
Your three options are copied below, and each one is broken up into multiple lines to highlight what they are doing:
delete *(A**)a;
A** ptrToPtrToA a = (A**)a;
A* ptrToA a2 = *ptrToPtrTo_a;
delete ptrTo_a;
No problem here. We ended up properly dereferencing the object
delete *((A**)a);
A** ptrToPtrTo_a = (A**)a;
A* ptrTo_a = *ptrToPtrTo_a;
delete ptrTo_a;
Hey, this one is exactly the same! The only thing the parenthesis do is change the order of operations. You happened to use the "native" order, so the parenthesis did nothing at all.
delete (A*)*a;
void* ptrTo_void = *a;
A* ptrTo_a = (A*)ptrToVoid;
delete ptrTo_a;
This also worked, it just took a different path.
Which one is correct? It's really a stylistic choice. I will give you my stylistic rule of thumb: always cast void pointers on separate lines. It makes it much clearer what is going on.
A* myObject = (A*)*a; // I prefer this one in this case, but what matters...
delete myObject; // ... is that it is distinct from the delete...
*a = 0; // ...not which cast is "best."
I like to do this because I find casting to/from void is a very tricky business when you really get down to it. There are a lot of places where it can go wrong. I like to create a clear line of code where I can mentally break apart all of my casting and make sure it does what I expect. Since I specify the type of the variable I want (myObject is a A*, and there's nothing the compiler can do to make it otherwise if I mess up), I am more likely to get a compiler error if I do something wrong. Its very easy to write casts from void where the compiler silently does a conversion you didn't expect. Then you're fixing a runtime error instead of a compile time error.
I also like to use that cast line as a good place to put comments explaining why I think it is safe to do the cast in the first place, such as "the only void pointers passed to this function are those created by my function in this same .cpp file, so I KNOW exactly what type is safe to cast to."
delete ptr is never going to compile in C. If it were, the first option would be correct, and the second option would be identical to it.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
For some reason, I have decided to never use dynamic memory allocation in my program. This means all the variables in my program are static and the "new" constructor is never used. But the following code crashes, and produces a stack overflow exception:
VeryLargeObject x; // Global variable -> static memory
void ResetTheObject()
{
x = VeryLargeObject();
}
Obviously, all I want to do is give x the default value of VeryLargeObject, which is a structure containing a lot of different variables, with their own constructors of varying complexity (so there's quite some initialization work to do). But here the language/compiler has decided that this should happen on the stack before being copied, and since VeryLargeObject is too large for the stack, my program crashes.
However I have found the solution to this problem:
VeryLargeObject x;
void ResetTheObject()
{
new (&x) VeryLargeObject();
}
I had never heard of this before, yet it does exactly what I want. This is a "placement new". It calls the constructor on the already allocated (or simply static) memory provided by a pointer.
My question, since I have the solution, is a rant: Why isn't this the default behavior of the first code ? If there isn't a less hacky way of doing this (i.e without the word "new" having anything to do with it), then why? Also why does it send me back the pointer, even though I just provided it? I thought C++ was a great language, but this seems kind of ugly and not very well-thought-out.
First of all, turning on optimization might get you what you want with the first syntax. Without it, here's what you asked the compiler to do:
Create a temporary object of type VeryLargeObject.
Assign that into a global variable called x.
Since temporary objects need storage, the compiler allocates them on the stack. What the compiler is doing is, literally, what you asked the compiler to do.
The compiler may, if optimizations are turned on, understand that what the sequence is and save the copy. This requires that the compiler can positively prove to itself that the old value of x will not get in the way in any way. Since you admit that the initialization is quite complex, you can forgive the compiler if it did not manage to do so.
You have two options. You can either create an in-place initialization function and call that instead of the constructor, or you can use placement new, like you did.
The danger with placement new, as you used it, is that it replaces the old value of x without properly destructing it. It simply assumes that x is uninitialized. If that's okay for your use, then go ahead and use it. The compiler, for its part, is not allowed to assume that.
I am doing some assignment and i am not good at understanding pointers. Please help me understand what argument i need to pass to this function.
void City::setList(List<City*> *l){list = l;}
Without seeing the definition for List (and because Google is case-insensitive), I can't give an exact answer, but you'll want to construct it something like this:
List<City*> myList;
Then (assuming List works like Java's List):
City c; //Or with constructor, or whatever
myList.add(&c);
To call your method:
// `d` is some other City
d.setList(&myList);
There's one major caveat, though: Unless you created c with new (which, given the syntax example I used here, you probably didn't), any pointers to it are going to be dangling as soon as c goes out of scope. You'll want to make sure you aren't doing that. And if you create it with new, you have to be sure to delete it later.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
In some code I have been working on, I am passing pointers into classes that aren't necessarily managed specifically by the class to which they are passed. If the class is destroyed then I check to see if the pointer's memory has or has not already been deallocated. The problem I have is that, if a pointer is deallocated and set to NULL before the class's destructor is called then I end up with a dangling pointer. The class ends up seeing the pointer is still non-NULL and tries to delete it which causes a segmentation fault. The best solution I could think of for this is to store the pointer by reference as shown below:
class PtrReferenceClass {
public:
PtrReferenceClass(int*& i_) : i(i_) {}
void run() {
if(i == NULL)
cout << "pointer is null\n";
else
cout << "pointer isn't null\n";
}
int*& i;
};
int main() {
int* i = new int(5);
PtrReferenceClass test(i);
test.run();
delete i;
i = NULL;
test.run();
return 0;
}
As expected, the output is:
pointer isn't null
pointer is null
Ofcourse when the pointer isn't store by reference I end up with a dangling pointer.
My question is as to whether or not this is generally considered to be a good programming practice. Are there any drawbacks to this solution or is there a better convention?
It depends upon what you are trying to accomplish.
If you want the memory around for your class use C++11's std::shared_ptr everywhere instead of an int*.
If you don't need the memory around for your class use C++11's std::weak_ptr.
As far as holding onto pointers in a class, that's not bad if they're wrapped in one of C++'s pointer wrappers. You can just hang onto raw pointers, but in general you should only do that if speed is an extreme concern.
You could check for NULLness in the destructor of PtrReferenceClass. A much better alternative whould be to use a shared_ptr or really clarify ownership of i.
Agree with #Paranaix in main thread comment, as well as #ToniBig, I can't really think of a situation where you would need this. Such a thing is probably to protect against horrible programmer error. You should also keep in mind that you are storing a reference to the pointer i, and that reference will be left dangling when the pointer i goes out of scope, regardless of whether the memory i refers to has been deallocated or not. SO in conclusion, please don't do this.
All you've done is trade one lifetime problem for another. The new problem may be easier to solve... or it may not.
Now you can detect that the object is gone... as long as something has kept the pointer variable alive.
Think carefully about your variable lifetimes, and whether a reference-to-pointer (or equivalently, pointer to pointer) makes sense should become clear.
There certainly are cases where double indirection is valuable. I will leave you with a quote: "Any problem in computer science can be solved by adding another layer of indirection"
These are options :
give ownership to class and manage lifecycle inside it.plus with safe
setter method for changing it when you want. Again do it if you have to create or obtain that pointer outside,otherwise just do all inside.
only pass that pointer to methods that will use it and when
needed.void run(int* i).
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Hello I have three classes
AbstSoccerTeam
PlayersSoccerTeam
PlayersFieldPlayerStates
PlayerSoccerTeam is a child class of AbstSoccerTeam.
bool AlanSoccerTeam::isClosestTeamMemberToSupportingPlayer(FieldPlayer* plyr)
is a method in player soccer team.
i am trying to call that method in the PlayersFieldPlayerStates class with this
PlayersSoccerTeam* sTeam;
sTeam->isClosestTeamMemberToSupportingPlayer(player);
I can get this problem when i run it
uninitialized local variable 'sTeam' used
I dont know whats going on or why i am getting this error.
Any help is apprecitated greatly
Thanking You
The problem is you have created a pointer to a PlayersSoccerTeam but you have not actually created the object itself yet.
I would suggest doing this.
PlayersSoccerTeam sTeam;
sTeam.isClosestTeamMemberToSupportingPlayer(player);
You could alternatively do this.
PlayersSoccerTeam* sTeam = new PlayersSoccerTeam()
sTeam->isClosestTeamMemberToSupportingPlayer(player);
As perhaps an interesting education experience create a constructor that prints something to stdout when it is run and then try doing these two options and yours to see what happens. A constructor will be run whenever a new object is created.
PlayersSoccerTeam* sTeam;
This line declares a pointer to a PlayersSoccerTeam and nothing else. All you get from this line is a pointer. It doesn't point anywhere in particular since you haven't initialized. There is no PlayersSoccerTeam anywhere to point to.
If you want an object of type PlayersSoccerTeam, then you just want:
PlayersSoccerTeam sTeam;
sTeam.isClosestTeamMemberToSupportingPlayer(player);
Since you told us about your hierarchy, it's possible that you want to use your PlayersSoccerTeam polymorphically as a AbstSoccerTeam. In this case you would need to use either a pointer or reference. This could be done like so:
AbstSoccerTeam* sTeam = new PlayersSoccerTeam();
// ...
delete sTeam;
Note that this still declares just a pointer, but the expression new PlayersSoccerTeam also creates a PlayersSoccerTeam object for the pointer to point to. Note that it's perfectly fine to assign a pointer to a PlayersSoccerTeam to a pointer to its parent AbstSoccerTeam - this is polymorphism in action. If you do this, you must make sure you delete sTeam; later, otherwise the object will be leaked.
A safer way to handle the user of dynamically allocated objects is to use a smart pointer, which you could do like so:
std::unique_ptr<AbstSoccerTeam> sTeam(new PlayersSoccerTeam());
Now you will not have to delete it because the std::unique_ptr takes care of that for you.
I have been assigned to work on some legacy C++ code in MFC. One of the things I am finding all over the place are allocations like the following:
struct Point
{
float x,y,z;
};
...
void someFunc( void )
{
int numPoints = ...;
Point* pArray = (Point*)new BYTE[ numPoints * sizeof(Point) ];
...
//do some stuff with points
...
delete [] pArray;
}
I realize that this code is atrociously wrong on so many levels (C-style cast, using new like malloc, confusing, etc). I also realize that if Point had defined a constructor it would not be called and weird things would happen at delete [] if a destructor had been defined.
Question: I am in the process of fixing these occurrences wherever they appear as a matter of course. However, I have never seen anything like this before and it has got me wondering. Does this code have the potential to cause memory leaks/corruption as it stands currently (no constructor/destructor, but with pointer type mismatch) or is it safe as long as the array just contains structs/primitive types?
Formally the code causes undefined behavior because of the pointer type mismatch in new[]/delete[]. In practice it should work fine.
The pointer type mismatch issue can easily be fixed by adding a cast to the delete-expression
delete [] (BYTE *) pArray;
If Point type is defined as shown in the question (i.e. with trivial constructor and destructor), then this correction solves all formal issues there are in this code. From the language point of view, the lifetime of an object with trivial constructor (destructor) begins (ends) simultaneously with its storage duration. I.e. there's no requirement to perform the actual invocation of constructor (destructor).
As long as the constructors and destructors do nothing, then you're safe.
As long as you assure that it really does invoke a matching delete[] for every new[], it shouldn't leak -- but if an exception might be thrown by any of the code that's been commented out, that's going to be difficult to assure (basically, you need to catch any possible exceptions, delete the memory, then re-throw the exception).
I would first try to figure out why the code was written that way in the first place. It might be simply because the programmer didn't know any better, or because they were trying to work around some funky defect int he compiler. But there might be a real reason that you are unaware of. If there is, then unless you understand that reason and its side effects, you may introduce a defect by changing this code.
That out of the way, and assuming there is no particular reason why the code needs to be this way now, you should be safe in changing the code to use more modern and correct constructs.
But why? I understand the motivation to make the code more correct. But what do you really gain by this? If the code works the way it is now (a big assumption), then by changing the code you possibly gain the benefit of making the code more understandable to future programmers, but every line of code you change introduces the possibility for a new bug to be written.
And if finally you do decide to go ahead with the change, why stop halfway? Consider getting rid of all the news and deletes altogether, and replace them with vectors etc.