Here is the code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
int *p = new int[2];
p[0] = 1;
p[1] = 2;
cout << *p++ << endl;
delete p;
return 0;
}
It can be compiled, but got a runtime error "free(): invalid pointer", followed by a memory map.
operating system ubuntu 10.10
compiler: g++ 4.4.3
You need to call the array-version of delete:
delete[] p;
EDIT: However, your real problem is that you're incrementing p.
The delete operators only work on the original pointers that were allocated.
Your call to delete must use the same pointer returned by your call to new.
In your code, you increment p with *p++, which due to operator precedence is interpreted as *(p++). Due to this, you are providing delete a pointer that the memory manager has never heard of.
Additionally, you should use delete[] to match a call to new[].
That being said, here is a guess of what you may have intended:
int *p = new int[2];
p[0] = 1;
p[1] = 2;
for(int i = 0; i < 2; i++)
cout << p[i] << endl;
delete[] p;
return 0;
Look a the code:
int *p1 = new int;
int *p2 = new int[2];
int *p3 = p1;
int *p1 = p2;
delete p3;
delete[] p1;
Pointers p1 and p2 have the same representation and the same set of allowed operations. For the compiler they are both int*.
Althougth the objects that they are pointing at are significantly different. The object from new int[2] at hegative offset has a header that contains the number of items in the array.
Working with array object is the same as if it were a scalar object. Only when this object is released, it is necessary to tell the compiler what sort of object is it. A simple object or an array. This is known source of bugs and confusion. Neverthless the language was defined in this way decades ago and we cannot change this.
It is also important to delete exactly the same pointer that was returned with new. This rule applies both to simple new and new[].
Related
Hello to understand more placement new, operator new, expression delete.. and separating the initialization from construction, I've tried this example:
int main(){
int* p = static_cast<int*>(operator new[](10 * sizeof(int)));
p = new(p)int[10];
for(int i = 0; i != 10; ++i)
p[i] = i * 7;
for(int i = 0; i != 10; ++i)
std::cout << p[i] << ", ";
operator delete[](p);
}
I've compiled it and run it and it works fine and checked it using Valgrind for memory leaks and nothing bad is reported. So is it how separate initialization from allocation?
What I am not sure about is that I used operator delete to free memory of the dynamic array but didn't destroy it (there is no placement delete). So is there some bad thing in my code?
As you noted, there is no placement delete. When using placement new, you have to call destructors manually, eg:
void* mem = operator new[](10 * sizeof(T));
T* p = new(mem) T[10];
...
for(int i = 0; i < 10; ++i)
p[i].~T();
operator delete[](mem);
Where T is the desired element type.
Calling destructors is not very important for POD types, like int, but it is important for non-POD types, like std::string, etc, to avoid leaks.
Here is my code
char * a()
{
char * c;
char b[10];
b[0] = 'h';
b[1] = 'i';
b[2] = '\0';
for (int i = 0; b[i] != '\0'; i++)
c[i] = b[i];
return c;
}
int main()
{
char * d;
d = a();
cout << d;
}
The problem is no output is being shown when it should have shown hi. Just wanted to know why this error occured.
"Edit": I finally realise it was due to not initialising the pointers. Pointer should always be initialised .
Example char * c= new char;
When you want an array you need to allocate space for the items. Just a pointer is not enough. Something like
char* c= new char[10]; //room for 10 chars
and be sure not to try indexes greater than 10-1=9. Accesing c[10] is undefined behaviour.
You can return that pointer (return c;). But don't forget to free the allocated memory when it isn't needed any more
d = a();
cout << d;
delete [] d; //free memory allocated with new d[...]
There are couple of errors in your program. Look that you create pointer of type char and then you do something like this:
c[i]
which will cause error. This is not what you want to do.
Also
you should not return pointer/reference to local variables. Local variables are destroyed when they leave scope (in your example b is destroyed at "return c;").
So when you create pointer to local object (notice that your variables are created on stack, not on heap) and return from function your pointer points to memory which is destroyed. It may worked it may not (undefined behaviour) but you should never do something like that.
I have a piece of code that deals with C++ array.
using namespace std;
#include <iostream>
int main(){
int *p;
p = new int[3];
for(int i = 0; i < 3; i++){
p[i] = i;
}
//delete[] p;
for(int i = 0;i <3; i++){
std::cout << *(p+i) << std::endl;
}
}
How does this code work? How does the memory location *(p+i) work? How is it different from using p[i]. What are the differences on the code if we uncomment the line delete[] p.
1) When you do this:
p = new int[3];
Now, p points to the first element of the dynamically allocated array.
When you do, *(p + i) will lead to simple pointer arithmetic. It will boil down to: value of (<address pointed by p> + <size of type pointed by p> * i) which is equivalent to doing p[i].
That's why it works.
2) In C++, unlike java, you have to explicitly clear the dynamically allocated memory using delete, as there is no GC in C++ (and will never be, as per Bjarne Stroustrup). Otherwise, the memory area will remain acquired for the application lifetime, thereby causing memory leak.
Suggestion:
Place your delete at the end of the program. Otherwise, the loop below it may give SIGSEGV.
Also, Avoid using new and delete as much as you can.
I'm currently learning pointer. And when I create a pointer to an array with int type, I found that I can directly index the pointer without deferencing the pointer and the compiler still output exact items in my array. I do not understand why this works and why we don't need to first deference the pointer.
Code that without dereference
int arraySize = 5;
int* theArray = new int[arraySize];
for(int i = 0; i < 5; i++)
{
theArray[i] = i;
}
for (int i = 0; I < 5; i++)
{
std::cout << theArray[i] << std::endl;
}
And this gives me the output
Output without derefercing
However, when I wrote like this:
for (int i = 0; i < 5; i++)
{
(*theArray)[i] = i;
}
My compiler says that: Error: expression must have pointer-to-object type. (I'm using Visual Studio 2013.)
Any help would be appreciated.
Code that without dereference
[ code ]
That's incorrect. You are most certainly dereferencing your pointer:
theArray[i] = i;
That's a pointer dereference. The [] operator dereferences the pointer. This is equivalent to:
*(theArray+i) = i;
As you know, adding or subtracting a value to a pointer advances or decrements the pointer, producing a new pointer value, and then the pointer gets dereferenced.
Also:
*p = q;
is equivalent to
p[0] = q;
The [] operator is just a shorthand for adding an offset to a pointer, and dereferencing the resulting pointer with the * operator. The end result is exactly the same.
I do not understand why this works and why we don't need to first deference the pointer.
The first version is correct:
for(int i = 0; i < 5; i++)
{
theArray[i] = i;
}
because theArray[i] is actually *(theArray + i) - essentially pointer arithmetic is equivalent to array index.
On the other hand, the 2nd version is incorrect:
for (int i = 0; i < 5; i++)
{
(*theArray)[i] = i;
}
That's because (*theArray)[i] is actually pointer to array (not the array itself), and so it caused a type mismatch as the compiler already suggested.
A few other answers correctly say that *(theArray + i) is equivalent to theArray[i]. But the point I think you missed when learning is that unlike most objects a pointer to an array is not a pointer to the array that is then dereferenced, and then array logic, it is only a pointer to the first element of the array. That's why this:
int *myIntPointer = new int[5];
is NEARLY the same as this:
int myIntArray[5]; // "True" array on the stack
But you can also point it at something else:
int myInt = 10;
delete [] myIntPointer;
myIntPointer = &myInt;
It's also why doing the follow CAN give a compiler warning, but can also work (depends on the compiler):
myIntPointer = myIntArray; // Sometimes works, sometimes doesn't, compiler dependent
That's because allocating an array with new int[size] returns a pointer to an int not a pointer to an "array" type.
It's a weird corner case of C/C++ that arrays and pointers interact this way. You also run into it if you try and pass one of the "true" arrays into a function.
theArray[i] literally corresponds to *(theArray + i) so it already dereferences the pointer.
Indeed when you try to call operator[] on *theArray it yields you an error because it expects a pointer, not a real object.
You're actually asking the wrong question for your misunderstanding — you should be asking why you can write
int* theArray = new int[arraySize];
In c++, array types are not like other types, and have a number of special cases and rules that make them behave differently from other types. In particular, new T[N] does not return a "pointer to an N-long array of T", it returns a "pointer to T". (specifically, to the first element of the newly created array)
For a more mindboggling example of this, observe:
typedef int T[5];
T* p = new T; // this does not compile
int* q = new T; // this does compile
Thanks in advance for people who help.
I am new to C++. I am learning the concept of smart pointer/shared pointer and using Visual Studio 2013RC. Following the example in wikipedia, I created a shared pointer like this
SharedPointer.cpp
#include <iostream>
#include <memory>
//using namespace std;
void main(){
std::shared_ptr<int> sp1(new int(5), std::default_delete<int[]>());
//std::shared_ptr<int> sp2 = sp1;
for (int i = 0; i < 5; i++) sp1.get()[i]= i;
for (int i = 0; i < 5; i++) std::cout << sp1.get()[i] << std::endl;
system("pause");
}
The program compiles and prints out 0,1,2,3,4 without any error, but then it comes the window saying "SharedPointer.exe has triggered a breakpoint."
Could anyone tell me what is the reason for this exception?
Thanks a lot
You should have used int[5] instead of int(5) here:
std::shared_ptr<int> sp1(new int[5], std::default_delete<int[]>());
Currently, your code allocates a single int which is initialized to 5, and then it tries to access it as an array of five ints (undefined behavior). After that, the smart pointer tries to delete that int with a delete[] operator (instead of a "plain" delete operator) which is also an undefined behavior.
sp1 is destroyed at the end of your program, causing the default deleter to run. The default deleter here invokes delete[], but since you didn't use new[], this is invalid.
In fact, from the looks of things, you meant new int[5] rather than new int(5), because you're also attempting to access five elements of this memory block where in fact you only allocated one.