What is the memory allocated to char *ptr:
#include <iostream>
using namespace std;
class A
{
private:
int count;
char *ptr;
public :
void print()
{
cout << "Addr " << &ptr << endl;
cout << "Addr " << *ptr << endl;
}
};
int main()
{
A obj;
obj.print();
A *obj1 = new A(obj);
obj1->print();
cin.get();
return 0;
}
I am using compiler provided copy constructor. I am interested in understanding how much memory will me allocated to the *ptr.
How much memory? Well, none at all. All you have is an unitialised char*, itself occupying sizeof(char*) bytes of memory. You will need to allocate memory yourself (perhaps with a new) and assign that memory to ptr. Don't forget to free the memory (perhaps with a delete) once you're done with it; typically done in a destructor.
Better still, use std::string which takes care of all the memory for you.
(P.S. technically the line cout << "Addr " << *ptr << endl; gives you undefined behaviour as you are dereferencing an unitialised pointer).
The char * alone will take up 4 bytes on a 32-bit machine, 8 bytes on a 64-bit machine. When you assign a memory (allocated using new perhaps) to ptr only the address of the memory is stored in ptr and the actual memory is allocated on the heap.
Related
I'm studying c++ and I'm reading about pointers. I'm curious about the following scenarios:
Scenario 1:
If I'm not mistaken, if the user types -1, there will be a memory leak:
#include <iostream>
using namespace std;
int main(){
int *p = new int;
cout << "Please enter a number: ";
cin >> *p;
if (*p == -1){
cout << "Exiting...";
return 0;
}
cout << "You entered: " << *p << endl;
delete p;
return 0;
}
Scenario 2:
But what happens in the following code? From what I've read and correct me if I'm wrong, when declaring a pointer like in the second scenario the pointer gets cleared out once you are out of scope. So if the user doesn't enter -1, the *p will be auto-cleared?
#include <iostream>
using namespace std;
int main(){
int x;
int *p = &x;
cout << "Please enter a number: ";
cin >> *p;
if (*p == -1){
cout << "Exiting...";
return 0;
}
cout << "You entered: " << *p << endl;
return 0;
}
What happens if I enter -1 in the second scenario?
Do not focus on the fact that you are using pointers that much. Memory leaks are usually about memory that the pointer points to, not about the pointer itself.
In this code:
int x;
int *p = &x;
there is no memory leak since there is no memory that would require explicit deallocation (no memory that has been allocated dynamically). int x is a variable with automatic storage duration that will be cleaned up automatically when the execution goes out of scope and int *p = &x; is just a pointer that holds the address of the memory where x resides.
But you are right that in code like:
Resource* r = new Resource();
if (something) {
return -1;
}
delete r;
there is a memory leak since there is a return path (exit path) that doesn't free the allocated memory. Note that the same would happen if the exception would be thrown instead of return being called... ensuring that all resources are freed properly is one of the main reasons why you should learn more about smart pointers, the RAII idiom and try to prefer objects with automatic storage duration over dynamically allocated ones.
In the second scenario, everything's fine.
Indeed, you haven't allocated memory (while you did in the first scenario). In the first case, the pointer "holds" the memory you allocated through new. In the second case, it points to a local variable with automatic-storage duration (i.e. it will be removed when going out of scope).
Simple rule: If you used new you must use delete (unless you're using a smart pointer). In the first scenario, if you type -1, you end up with one new and zero delete, which yields a memory leak. In the second case, you haven't allocated anything, the pointer points to memory that is already managed.
In the second scenario you do not allocate memory so you should not bother about some memory leak. You have to use delete or delete[] if you explicitly allocate memory with new or new for arrays.
In the second scenario p points to local variable x. It is the compiler that allocated memory for x in stack. So it is the compiler that properly will free this memory after x will be out of its scope.
In the first main, you dynamically allocating the int and manually delete it when exiting from main. However, if int is equal to -1, you do not delete it and return so that's why you have a memory leak.
In second example, the int is allocated on the stack and you're taking the address of it. When main returns, the int is deallocated automatically. If you tried to call delete on it in the main, you would get a crash.
lI'm running a C++ program on a 64-bit machine. The program dynamically creates objects from different classes. When I print out the value of the pointers (not dereferencing) to those objects using cout, the address of some objects is 48-bits while the address of other objects is 28-bits! I have read that some processors currently only support 48-bits, but why then do I get an output of 28-bits in some cases? What does that even mean?!
Edit:
This is part of a big project. So, I won't be able to post the exact code. But here is what is basically happening. I do realize that the objects need to be deleted to avoid memory leaks.
ClassA *pA = new ClassA();
ClassB *pB = new ClassB();
cout << "Address of ClassA object = " << pA << " , Address of ClassB object = " << pB << endl;
pA = new ClassA();
pB = new ClassB();
cout << "Address of ClassA object = " << pA << " , Address of ClassB object = " << pB << endl;
Now the output that I get is the following:
Address of ClassA object = 0x7fcda0001150 , Address of ClassB object = 0x19f1160
Address of ClassA object = 0x26c77c0 , Address of ClassB object = 0x1aba400
I guess, you just observed that objects are allocated in different memory regions:
Objects with static linkage are generally located in the data segment next to the segment with the program code and typically have relatively small values.
Objects on the stack are typically located at the far end of the memory with the stack normally growing downwards. They have, thus, normally fairly large values.
Objects allocated on the heap are typically somewhere between the data segment and the stack. Depending on how the memory allocation decides to allocate memory, the value are likely to start small, i.e., just above the data segment or fairly large, i.e., just below the stack.
How systems really lay out their memory is entirely up to the system, however. Some systems may have entirely different memory layouts, have stacks growing upwards, etc. Here is a simple program demonstrating this effect:
#include <iostream>
int main()
{
static int a(0);
static int const b(0);
int c(0);
int* d(new int(0));
std::cout << "a=" << &a << '\n'
<< "b=" << &b << '\n'
<< "c=" << &c << '\n'
<< "d=" << d << '\n';
delete d;
}
On my system, this program prints
a=0x103504064
b=0x103503f7c
c=0x7fff5c6fca8c
d=0x7f92204000e0
I guess, something like this difference led you to the assumption that pointers are different but it is just that the value formatted require a different number of digits: all int*s used will have the same size.
I have created objects by using new, but then have dereferenced them before adding them to a vector. Despite trawling the internet I cannot work out how I can call delete on these items. I want to do this just using standard C++ and STL I don't want (e.g.) to use Boost libraries.
As you can see a, b and c lose scope and I am left with what I presume to be copies in the vector. How can I go about deleting these. I don't want to store pointers in the array as I will need to pass an API function an array of doubles.
Please someone - how do I delete these objects?
#include <iostream>
#include <vector>
using namespace std;
vector<double> vectorDouble;
void createObjects();
void createObjects() {
double* a=new double(13);
double* b=new double(14);
double* c=new double(15);
//a,b and c are not contiguous memory blocks
cout << "memory location of a: " << a << endl;
cout << "memory location of b: " << b << endl;
cout << "memory location of c: " << c << endl;
vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);
}
int main() {
createObjects();
//the memory addresses are contiguous 8 byte chunks
cout << "vector memory at 0: " << &(vectorDouble[0]) << endl;
cout << "vector memory at 1: " << &(vectorDouble[1]) << endl;
cout << "vector memory at 2: " << &(vectorDouble[2]) << endl;
//get pointer to the 2nd element
double *P=&(vectorDouble[1]);
//dereference and look inside - two memory locations both contain the value 14
cout << "vector Pointer P ["<< P <<"] contains " << *P <<endl;
//Which should I call delete on? I have lost reference to the original pointers.
//How should I call delete on the vector?
cout << "deleting pointer that references 2nd vector element" << endl;
delete P; //********* CRASH **********
cout << "Done deleting" << endl;
}
The objects you need to delete are not in the vector, because your vector elements are not created with new. You are just passing the copy of the malloc'd doubles, not the actual allocated double to the vector, when you use the dereference operator in the push_back.
You are actually just leaking them - your code would run fine without allocating doubles:
void createObjects() {
vectorDouble.push_back(13);
vectorDouble.push_back(14);
vectorDouble.push_back(15);
}
As everyone points out, there is no reason whatsoever to invoke new in your program:
void createObjects() {
vectorDouble.push_back(13);
vectorDouble.push_back(14);
vectorDouble.push_back(15);
}
Suppose, however, that you do have some reason to call new. (I can't imagine what it might be, but let's assume you are a genius). Here is how you would do that:
void createObjects() {
double* a=new double(13);
double* b=new double(14);
double* c=new double(15);
//a,b and c are not contiguous memory blocks
cout << "memory location of a: " << a << endl;
cout << "memory location of b: " << b << endl;
cout << "memory location of c: " << c << endl;
vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);
delete a;
delete b;
delete c;
}
You see, the push_back doesn't put a copy of your pointer in the vector, it puts a copy of your object in the vector. Once you've made the copy of your object, then your object's memory serves no continuing purpose, and can be destroyed.
The function createObjects is not putting the allocated values into the vector; it is putting in the values and then leaking the memory that a, b, and c pointed to. The call:
vectorDouble.push_back(*a);
stores the value pointed to by a in the vector (*a dereferences the pointer, which you probably already know). Once that function returns, the pointers are lost. You cannot retrieve them from the vector. You would either need to make a vector of pointers to doubles or (more likely) don't even allocate values; just store the doubles.
I think I've got the problem, on:
vectorDouble.push_back(*a);
vectorDouble.push_back(*b);
vectorDouble.push_back(*c);
You are passing a, b and c as values so the array don't really contains the variables you have created (that's why they now have different memory address, they are a copy of the content of your variables!). Then you can delete the variables inside the method, don't use pointers inside the method or use an double* vector.
Your leak is in createObjects(), because std::vector<>::push_back() makes a copy of its argument. You should delete the pointer before the end of scope of createObjects().
That said, I don't see why you use dynamic allocation to begin with. If you can avoid that please do (and you can, with a smart pointer like std::unique_ptr<>, or better yet with plain old doubles).
#include <iostream>
int main()
{
int anything[] = {5};
int *something = new int;
*something = 5;
std::cout << &anything << "==" << &anything[0] << "==" << anything << std::endl;
std::cout << &something << "!=" << &something[0] << "==" << something << std::endl;
}
Why is the memory address in &something different from &something[0] and something? Although it is a dynamic allocation, I don't understand why the memory address is different. I tried it with more than one value; it's the same thing. Here I used one value for both for simplicity.
&something is the memory address of the pointer itself (hey, it needs to store that value somewhere!), while &something[0] is the address of the actual memory that is storing your stuff.
something is a pointer. &something is the address of that pointer. &something[0] is the address of the first element pointed to by the pointer, which is completely different from the address of the pointer. something is the value of the pointer, which is also the address of the element that is pointed to.
I'm sure this topic has been covered many times before, I hope I did it justice.
I'm reading "Thinking in C++" and I'm confused by the new operator. Here is the code from the book:
//: C13:ArrayOperatorNew.cpp
// Operator new for arrays
#include <new> // Size_t definition
#include <fstream>
using namespace std;
ofstream trace("ArrayOperatorNew.out");
class Widget
{
enum { sz = 10 };
int i[sz];
public:
Widget() { trace << "*"; }
~Widget() { trace << "~"; }
void* operator new(size_t sz)
{
trace << "Widget::new: "
<< sz << " bytes" << endl;
return ::new char[sz];
}
void operator delete(void* p)
{
trace << "Widget::delete" << endl;
::delete []p;
}
void* operator new[](size_t sz)
{
trace << "Widget::new[]: "
<< sz << " bytes" << endl;
return ::new char[sz];
}
void operator delete[](void* p)
{
trace << "Widget::delete[]" << endl;
::delete []p;
}
};
int main()
{
trace << "new Widget" << endl;
Widget* w = new Widget;
trace << "\ndelete Widget" << endl;
delete w;
trace << "\nnew Widget[25]" << endl;
Widget* wa = new Widget[25];
trace << "\ndelete []Widget" << endl;
delete []wa;
} ///:~
and here is the content of the trace in "ArrayOperatorNew.out"
new Widget
Widget::new: 40 bytes
*
delete Widget
~Widget::delete
new Widget[25]
Widget::new[]: 1004 bytes
*************************
delete []Widget
~~~~~~~~~~~~~~~~~~~~~~~~~
Widget::delete[]
I'm confused about the number 1004. Why it's not 1000? The book says:
This extra four bytes is where the
system keeps information about the
array, in particular, the number of
objects in the array.
But what's the system? How is this accomplished? Compiler helps here?
When using new[] the runtime needs some way to remember the size of the array allocated, so it knows how much to deallocate when using delete[]. In your particular implementation it's way of remembering is allocating the extra four bytes which hold the size (it doesn't have to work this way).
You can read more about this in the C++ FAQ.
This FAQ After p = new Fred[n], how does the compiler know there are n objects to be destructed during delete[] p? answers exactly this question.
That's a compiler-dependent detail.
When delete[] is invoked it is passed only one parameter - the pointer to the array. In order to run correctly it has to know the number of elements to execute the destructors on exactly the right number of objects. So it has to get that information somewhere.
The typical approach is that new[] prepends the array payload with an extra size_t that stores the number of elements. Thus the amount of space allocated will be
sizeof( size_t ) + numberOfElements * sizeof ( ObjectType )
When allocating an array with new then, an additional word is used in the beginning of the allocated block to keep the number of allocated bytes.
As the C++ array do not keep information about their size, the memory manager must keep tabs over the size of allocated memory, when delete[] is used the number of allocated byes is read and then the memory manager fees that amount of memory.
that is the reason why calling delete[] for a single variable can be disastrous
and calling delete for an array causes a memory leak.
The memory management has to keep some information about the size of the memory block. Without that information, delete / delete[] can not work correctly (in case of delete, this information may not be necessary sinc the compiler knows the size of object being deleted).
How the information is kept and where is an implementation detail of new/delete. It may change depending on the compiler or the memory management library you use (e.g. SmartHeap).
Sometimes additional memory is allocated to detect programming errors (like writing over the boundary of allocated memory).