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 5 years ago.
Improve this question
I know if I create a pointer in the header file, I should always delete it when the destructor is being called, but what about if I create a pointer inside of a function. I know basic variables get destroyed at the end of the block, is it the same for pointers?
For example:
Class::Function()
{
int i = 3; // This gets destroyed after the function ends
int* j = 5; // What about this? Do I have to delete it somewhere to keep from a leak?
}
If I initialize j inside of the constructor, I would say delete j; to prevent leaks, etc. Is there something I should do in this case?
Assigning int value to pointer
int* j = 5;
is illegal because you are storing int to int*. Anyway you can cast it
int* j = reinterpret_cast<int*>( 5 );
but dereferencing this pointer would lead to undefined behavior, since you dont know where does that pointer point.
You should init pointers like that
int* j = nullptr;
Since c++11 you cant create instance of nullptr_t and assign it.
nullptr_t initPointer;
int* j = initPointer;
If you dont use new operator to assign memory to pointer, you can't delete this pointer, it would lead to undefined behavior. Otherwise if you use new you need matching delete or you would get memory leak. If you want to check your program have memory leaks, check this thread and choose one tool. I can recommend valgrind.
Every call to new needs a matching call to delete. If you have more new's than delete's, you get memory leaks. If the opposite, you get double deletes. In your case, if you never called new, then there's no need for delete!
There are tools out there to help match your new's and deletes. My personal favorite is cppcheck. It's super quick and easy to use, and it runs on the c++ source code! It generally does a good job at catching unmatched new and delete calls.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I have a class that includes a std::uint_8 pointer and the destructor should be called to delete the allocated memory. The issue I'm having is that a complier error occurs and states that the memory was not allocated, but I know I allocated it in my default constructor.
Here's my default constructor:
BigInteger::BigInteger() {
unsigned char aArray [4];
aArray[0] = 0;
m_number = new unsigned char[4]
m_number = aArray;
m_digitCount = 0;
m_sizeReserved = 4;
}
and here's my destructor:
BigInteger::~BigInteger() {
delete [] m_number;
}
unsigned char aArray [4] here you create an array of 4 elements on the stack. These will go out of scope once the constructor has finished.
m_number = new unsigned char[4] now you create 4 elements on the heap. You allocate the memory and you'll be in charge of cleaning it up. Not an issue, you do so in the destructor.
m_number = aArray; now you change what m_number is pointing to, effectively losing a pointer to the memory you allocated. Now you have a leak.
Any use of m_number outside of this constructor is now undefined behaviour, because you're accessing memory you no longer own.
delete [] m_number; now you're deleting memory you don't own. UB.
Don't reassign m_number and you won't have these issues. Better yet, use std::vector and watch as these manual memory management problems melt away.
That line
m_number = aArray;
assigns a local variable's address to m_number.
That address cannot be used in conjunction with delete [] m_number;, the memory address allocated with new unsigned char[4] is overridden and lost after that assignment.
You have a classical scenario of a memory leak. In essence what you are doing is the following:
Allocate memory (m_number = new unsigned char[4])
Override the pointer that points to that allocated memory (m_number = aArray)
Never delete the allocated memory as you no longer know where it is - you have lost the pointer to it (it got overwritten)
Array with size 0 Has good explanations of zero-length arrays and is certainly worthwhile and pertinent. I am not seeing it compare zero-length with single-element arrays and with pointer-to-variable.
When I asked before (Is c++ delete equivalent to delete[1]?) I did not express myself well. My question seemed to be the same or included in more general answers about new, new[], delete, and delete[]. Some understood that I was asking only about a single element. All answers in comments seemed correct and consistent.
There is a question that looks like the same as this question. But the body is about using C++ and Java together. Here, we are talking only about C++.
Checking my understanding
I will present pairs of proposed equivalent statements. The statements are declarations or instantiations of a pointer to a single variable followed by a pointer to an array of one element. Then I will state why I would think they are equivalent or not.
Are these pairs equivalent?
int one = 1;
// Sample 1. Same in the sense of pointing to an address somewhere
// whose contents equal one. Also same in the sense of not being able to
// change to point to a different address:
int * const p_int = &one;
int a_int[1] = {1};
// Sample 2.
int * p_int1 = new int;
int * a_int1 = new int[1];
// Sample 3.
delete p_int1;
delete[] a_int1;
// Sample 4. If Sample 3 is an equivalent pair, then (given Sample 2)
// we can write
delete[] p_int1;
delete a_int1;
Granted, Sample 4 is bad practice.
I am thinking: "delete" will call the destructor of the object. delete[] will call the destructor for each element of the array, and then call the destructor for the array. new in Sample 2 would malloc (so to speak) the variable. new[] would malloc an array of one element, then malloc the one element. And then that one element would be set equal to 1. So, I'm thinking THAT'S why I need to call delete[] and not delete when I have an array of even one element. Am I understanding?
And if I am understanding, then calling delete instead of delete[] to free an array of one element, then I will certainly have a memory leak. A memory leak is the specific "bad thing" that will happen.
However, what about this:
int * a_int0 = new int[0];
delete a_int0;
Would THAT result in a memory leak?
I invite corrections of my misuse of terminology and anything else.
Sample 1:
int const * p_int = &one;
int a_int[1] = {1};
NO, these are not equivalent. A pointer is not the same thing as an array. They are not equivalent for the same reason that 1 is not the same as std::vector<int>{1}: a range of one element is not the same thing as one element.
Sample 2:
int * p_int1 = new int;
int * a_int1 = new int[1];
These are sort of equivalent. You have to delete them differently, but otherwise the way you would use p_int1 and a_int1 is the same. You could treat either as a range (ending at p_int1+1 and a_int1+1, respectively).
Sample 3:
delete p_int1;
delete[] a_int1;
These are I suppose equivalent in the sense that both correctly deallocate the respective memory of the two variables.
Sample 4:
delete[] p_int1;
delete a_int1;
These are I suppose equivalent in the sense that both incorrectly deallocate the respective memory of the two variables.
int const * p_int = &one;
int a_int[1] = {1};
They are not equivalent, the first is a pointer to another variable, the other a mere array of size one, initialized straight away with the value one.
Understand this: pointers are entities in themselves, distinct from what they point to. Which is to say, the memory address of your p_int there, is entirely different from the memory address of your variable one. What's now stored in your p_int however, is the memory address of your variable one.
// Sample 2.
int * p_int1 = new int;
int * a_int1 = new int[1];
Here though, they are effectively the same thing in terms of memory allocation. In both cases you create a single int on the heap(new means heap space), and both pointers are immediately assigned the address of those heap allocated ints. The latter shouldn't be used in practice though, even though it's technically not doing anything outright wrong, it's confusing to read for humans as it conveys the notion that there is an array of objects, when there is in reality just one object, ie no arrayment has taken place.
// Sample 3.
delete p_int1;
delete[] a_int1;
Personally, I've never used the "array" delete, but yeah, what you're saying is the right idea: delete[] essentially means "call delete on every element in the array", while regular delete means "delete that one object the pointer points to".
// Sample 4. If Sample 3 is an equivalent pair, then (given Sample 2)
// we can write
delete[] p_int1;
delete a_int1;
Delete on array is undefined according to the standard, which means we don't really know what'll happen. Some compilers may be smart enough to see what you mean is a regular delete and vice versa, or they may not, in any case this is risky behavior, and as you say bad practice.
Edit: I missed your last point. In short, I don't know.
new int[0];
Basically means "allocate space for 0 objects of type int". That of course means 0 * 4, ie 0 bytes. As for memory leaks, what seems intuitive is no, as no memory has been allocated, so if the pointer goes out of scope, there is nothing on the heap anyway. I can't give a more in dept answer than that. My guess is that this is an example of undefined behavior, that doesn't have any consequences at all.
However, memory leaks happen when you do this:
void foo()
{
int* ptr = new int;
}
Notice how no delete is called as the function returns. The pointer ptr itself gets deallocated automatically, since it's located on the stack(IE automatic memory), while the int itself is not. Since heap memory isn't automatically deallocated, that tiny int will no longer be addressable, since you got no pointer to it anymore in your stack. Basically, those 4 bytes of heap memory will be marked as "in use" by the operating system, for as long as the process runs, so it won't be allocated a second time.
Edit2: I need to improve my reading comprehension, didn't notice you did delete the variable. Doesn't change much though: You never have memory leaks when you remember to delete, memory leaks arise when you forget to call delete on heap allocated objects(ie new) prior to return from the scope the pointer to heap memory was located. My example is the simplest one I could think of.
This is a syntax-only answer. I checked this in a debugger with the following code:
// Equivalence Test 1.
*p_int = 2;
p_int[0] = 3;
*a_int = 2;
a_int[0] = 3;
Because I can access and manipulate the declarations as an array or as a pointer to variable, I think the declarations are syntactically equivalent, at least approximately.
I have to apologize
(1) I did not think to define my terms clearly. And it is very hard to talk about anything without my defining my terms. I should have realized and stated that I was thinking syntax and what a typical compiler would probably do. (2) I should have thought of checking in a debugger much earlier.
I think the previous answers are correct semantically. And of course good programming practice would declare an array when an array is the meaning, etc. for a pointer to variable.
I appreciate the attention that has been given to my question. And I hope you can be accepting of my slowness to figure out what I am trying to say and ask.
I figure that the other declarations can be checked out similarly in a debugger to see whether they are syntactically equivalent.
A Compiler's generating the same assembly would show syntactic equivalence. But if the assembly generated differs, then the assembly needs to be studied to see whether each does the same thing or not.
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
Consider the following code:
struct A {
int someInt;
};
A *a = new A;
A *b;
delete a; // ok
delete b; // crash
It crashes, but I don't know why. I thought deleting null pointers is a no-op.
Do I even need to delete structs? Is it bad practice to create structs on the heap? Is it better to create them on the stack?
Deleting null pointers is a no-op, yes, so if b were a null pointer then you'd be fine.
But it's not. It's an uninitialised variable with an indeterminate value.
Here's a null pointer:
A* b = nullptr;
(If you write A* b; at global scope, or if you write static A* b; in a function, or if you are defining a static class member, then b has static storage duration and is automatically zero-initialised for you; this is the one exception to the rule.)
And, yes, you should avoid dynamic allocation where possible — using it for no good reason complicates your code for, well, for no good reason.
b is a uninitialized pointer. There is nothing to delete.
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
Let's say I have this code
void foo()
{
int x = 0;
cout << x << endl;
}
does x disappear from memory(goes out of scope) when the function returns?
If I make this
void foo()
{
int *x = new int
*x = 0;
cout << x << endl;
}
is that the correct way to make x not disappear when the function ends?
Also, since that variable is declared inside the function, how do I access it in the main after the function has been executed?
When should I use delete? Does the memory allocated on the heap become free when the program is closed or I have to manually do that?
1) Yes, variables declared in the function goes out of scope once stack unwinding happens.
2) To allocate the memory in the heap yes, you can use 'new' allocator.
3) To avail the memory allocated from anywhere in the program, either you return the pointer from the function itself, or assing in the global variable.
4) When you the variable is no more usable, then you can delete with 'delete' operator.
Hope this helps!!.
Yes, x goes out of scope when foo() returns. However x is automatic, which means it is probably allocated on the stack, and possibly its contents will remain for some time in the same place of memory - but you never know how long it will last until some other function overwrites it.
And with sufficient level of optimization such simple x will be allocated in a CPU register, so it may get overwritten even before the function terminates, just after out<<x execution.
Yes, x goes out of scope when foo() returns, so you loose the access to the variable allocated on a heap. You can, however, return x from your function, or store the pointer value in some external variable, so it might be retrieved and used after the foo() termination.
You should use delete when you no longer need a variable.
Unfreed memory is returned automatically to the system together with the whole heap when the program teminates. However, if your allocated objects reserve some external resources (IO streams, system semaphores etc) it's good to delete them so those resources are released properly.
BTW, if x is a pointer and you want to printout the int value rather than its memory address, you should use a dereference operator on the pointing variable: cout << *x.
Yes x goes out of scope when the function exits.
Yes. The technical name for "not disappear" is a memory leak. In this code example you lose the pointer, since it goes out of scope after the function as discussed in 1, so you won't be able to delete the memory. Smart pointers are much better.
In general, to access something from a function when the function call has finished, you are best off returning what you want.
e.g.
int * foo()
{
int *x = new int;
*x = 0;
cout << x << endl;
return x;
}
I suggest you read up on smart pointers instead though.
Prefer doing like this, in this order:
Copy or move the result of the function outside.
Use smart pointers if the type is being used polymorphically or cannot be copied/moved.
Try to use std::unique_ptr when you can.
Use std::shared_ptr when you must.
In general, in my experience, you can make types movable most of the time.
Copyability depends on the kind of class you are managing. Classes that access resources
such as filesystem, threads, locks, etc. are difficult to copy or it makes no sense to copy them.
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
Consider the following code:
int cnt = 10;
Object* objects = new Object[cnt];
for(int i = 0; i < cnt; i++) {
*(objects + i) = Object();
}
//All objects are destroyed here!
All objects are destroyed when the program exits the loop. I think it's because they go out of scope (When I debug it, the destructor of each object is called). How do I store them on the heap but still reference them from the pointer? Why is the following not allowed?
*(objects + i) = new Object(); //not allowed by compiler
UPDATE:
It seems that only the temporary objects are being destroyed. I was looking for a way to store these temporary objects on the heap (So that they are not temporary) but that would create a memory leak. The confusion came from the fact that I didn't know that an array of objects is automatically initialized on creation (I came from C#).
Also, what happens when I call delete[] objects? From what I've read, only the pointer is actually deleted. Does that mean I have to cycle through each object and manually delete it? If the object itself also stores other objects (on the heap), do I have to destroy those objects in its destructor method? (Which will automatically be called when I use destroy object).
When you execute *(objects + i) = Object(), a temporary Object instance is created on the stack and passed to the assignment-operator of class Object, with this being objects+i.
If no assignment-operator is defined, then the default assignment-operator is invoked.
The default assignment-operator simply copies each one of the member fields of the input object into the corresponding member field of this (in a manner similar to that of a structure-assignment operation).
So the comment //All objects are destroyed here! is wrong.
When you execute Object* objects = new Object[cnt], an array of Object instances is created, and the default (empty) constructor is invoked for each one of them.
So the loop which executes *(objects + i) = Object() for each instance is completely redundant here, because you are essentially creating an Object instance using the default (empty) constructor and then passing it to the assignment-operator, for each instance in the array.