I am initializing a char pointer with some random values, and when I am trying to delete it, I am unable to. Why is that?
Here is what I am doing:
int main()
{
char *s = new char[50]; /*
* I know there is no reason for
* using new if initializing, but
* in order to use delete we need
* to allocate using new.
*/
s = "Harry";
delete s;
return 0;
}
If you really want to practice with pointer, you need to fix your code. The main problem is you are trying to assign string literal( which is const char[6] in here) to pointer s then try to modify it by calling delete which invoke undefined behavior(UB).
char *s = new char[50];
strcpy(s, "Harry"); // don't assign string literal to it
// re-assign pointer to string literal,
// lost pre-allocated memory position and caused delete to fail
// it's UB to modify string literal
delete []s; // new[]/delete[], new/delete need to be called in pair.
Just use std::string instead.
#include <string>
std::string s("Harry"); // no worries
The problem is that after this assignment:
s = "Harry";
Then your s is no longer pointing to the memory you have allocated. It is pointing to a different array, or a const char[6] to be precise. The other array isn't dynamically allocated, and isn't on the heap. You can't delete variables that aren't on the heap.
In addition, by changing the s pointer to point at something else before the dynamically allocated memory has been freed, you introduce a memory leak.
To fix your code, either copy "Harry" into the s array by using strcpy, or use std::string instead.
You should never initialize a pointer with a string constant this way. It creates memory leaks which can be very dangerous.
When you allocated the memory using new, a 50 char memory was allocated in heap and its pointer is returned in s. when you were trying to initializing this value (wrong way) using s="Harry" , a new space is allocated in stack, initialized with this value and returned in s.
This memory allocated in stack cannot be deleted using delete call because it works only on heap.
Also, the memory initially allocated using new can no longer be accessed using s. Thus, you have a memory leak over here.
You can notice a different address in your pointer s after this wrong initialization by making small changes in your program:
#include <stdio.h>
int main()
{
char *s = new char[50];
printf("\n %u",s); // print address before init
s = "Harry";
printf("\n %u",s); // print address after init
// delete s; // cannot delete from stack
return 0;
}
Like others have already suggested, an array of character should be initialized using
strcpy(s, "Harry");
A char* is not actually a string. It is a pointer to some character with more characters to follow and ending with '\0'.
A character literal in C (and thus in C++) like "abc" is just an array of characters, with the compiler silently adding a '\0'. When you assign an array to a pointer, the array silently converts a pointer to the first element.
s = "Harry" means, the pointer s is assigned the address of the first character in the string literal "Harry". So the old value is lost and as this was the address of a dynamically allocated character array, leakage is supposed to happen.
std::strcpy, on the other hand, copies a string character by character from one array to another array. No pointers will be changed, only pieces of memory are copied. The pointer to the target array still points to the target array afterwards, only the data in that array has changed.
I don't think this occurs with initialized pointers.
When using a pointer, you can only delete (free) the memory it's pointing to, not the pointer itself, since it's an automatic object and will be deleted at the end of the block.
Related
As far as i know, std::string creates a ident array-copy of its content when you call the c_str()/data() methods (with/out terminating NUL-char, does not matter here). Anyway, does the object also take care of freeing this array or do I have to?
In short:
std::string hello("content");
const char* Ptr = hello.c_str();
// use it....
delete[] Ptr; //// really ???
I just want to be on the safe side when it comes to memory allocation.
No you don't need to deallocate the ptr pointer.
ptr points to a non modifyable string located somewhere to an internal location(actually this is implementation detail of the compilers).
Reference:
C++ documentation:
const char* c_str ( ) const;
Get C string equivalent
Generates a null-terminated sequence of characters (c-string) with the same content as the string object and returns it as a pointer to an array of characters.
A terminating null character is automatically appended.
The returned array points to an internal location with the required storage space for this sequence of characters plus its terminating null-character, but the values in this array should not be modified in the program and are only guaranteed to remain unchanged until the next call to a non-constant member function of the string object.
std::string handles this pointer so don't release it. Moreover, there are two limitations on using this pointer:
1. Don't modify string that is pointed by this pointer, it is read-only.
2. This pointer may become invalid after calling other std::string methods.
No need, the dtor of the string class will handle the destruction of the string so when 'hello' goes out of scope it is freed.
Not only you don't need to free the pointer but you in fact should not. Otherwise the destructor of std::string will attempt to free it again which may result in various errors depending on the platform.
The std::string class is responsible for freeing the memory allocated to contain the characters of the string when an object of the class is destructed. So if you do
delete[] Ptr;
before or after hello object is destructed (leaves the C++ {} scope it was created in), your program will run into a problem of trying to free a memory block that is already freed.
void setCString(char* s){
char* t = new char[strlen(s) + 1];
strcpy(t, s);
delete[] m_cstring; //del old contents from member var
m_cstring = t;
}
rA.setCString("Bii");
Isn't this a memory leak? "Bii" is created in memory and a pointer to it (s) is passed to the function. In the function a new allocation is made and the contents of the s array are copied to the new t array.
When the function ends, s goes out of scope and is deleted but the initial original array that s pointed to is not deleted.
If this is a memory leak, how can it be fixed (sticking to c string as array... no std::string)?
"Loosing" the (probably sole) pointer to a string literal is not considered a memory leak, because string literals cannot be "freed" and its "allocated memory" reused. Actually freeing a string literal is undefined behaviour. So no "leak" in its common sense; just a string literal which might not be used any more.
I have some issues about this code:
1) Why the output returns trash if I delete the first cell ?
int b = 1025;
char *v = new char[sizeof(int)];
memcpy(v,&b,sizeof(int));
char *pp = (char*)v;
++pp;
delete v; // is equal delete &v[0]
cout<<"salida"<<*pp;
2) How to delete dynamically allocated memory when i have void* ...
void *pv = v;
is correct
delete pv;
or
delete [](char*) pv;
i think what you are trying to do is deallocating the dynamically allocated memory..
first a pointer is always size of an int.
It only handles data locations(references).
A char pointer can store the address of a char type variable.
A void pointer can store the address of any data type.
so delete option works for both type of data types.
it simply deallocate the space and make it available on heap
A call to new[] needs to be matched by a call to delete[] on the same memory address and using the same pointer type.
A call to new needs to be matched by a call to delete on the same memory address and using the same pointer type.
If you mix things up, then you're invoking undefined behavior and will eventually have problems.
Maybe you'll occasionally be "lucky" and get away with it in certain simple circumstances because of how certain compilers have implemented dynamically allocated memory, but it's still a bad idea and could break at any time. If you try this with a class type which has a destructor, then one common consequence is that the destructor will not be properly run on some or all of the instances. But of course there are other possibilities, such as heap corruption.
So the result of a new char[] statement must be deallocated by a delete[] statement on a pointer of type char*.
You can't delete just one element of a dynamically-allocated array. If you allocate an array with new[], you can only delete the entire array, and you must use delete[], not delete.
Doing
char *v = new char[sizeof(int)];
and then
delete v;
invokes undefined behavior. You need to do delete[] v, and then you can no longer use pp because it points to something that's been deleted.
What exactly are you trying to delete, the char *v or void *pv?
If you want to delete char *v,
delete[] v;
v = NULL; // v still exists, but it's a dangling pointer now, so we set it to NULL (or 0)
Usually when you want to delete something, it has to be paired with new. So I think if you want to delete void *pv, you have to initialize the void pointer to new like this:
void** pv = new(void*); // Create a void pointer using new
pv = (char *)v;
delete pv;
Consider the following situation in C++:
void Light::setColor(Color* &color, ColorType type)
{
color = new Color(type);
}
Do I have to delete the value that might has been stored at pointer "color" before, since C++ does not delete such objects itself? I have tried different combinations:
delete *&color;
delete &color;
delete &*color;
Nothing works.
delete color;
Will work and learn how to spell
If you have just this function you cannot say whether or not color was allocated beforehand.
You may have a nullptr or a valid pointer in both case delete color; will work (because there is no need to test for nullptr when calling delete).
But you may get something wrong (a non initialized pointer or even a pointer to a object allocated on the stack) and in that case delete will fail.
I would recommand that you use std::shared_ptr<Color> it will solve your ownership problems.
void Light::setColor(std::shared_ptr<Color>& color, ColorType type)
{
color = std::make_shared<Color>(type);
}
Or better:
std::shared_ptr<Color> Light::setColor(ColorType type)
{
return std::make_shared<Color>(type);
}
But by convention, a method starting with "set" is supposed to assign something to a internal member. createColor would be better.
This is a more general question regarding pointers.
When you have a pointer to an object, you are referencing a part of memory. When you delete that memory, it gets freed.
So, if you do:
color = new Color(...);
you are allocating a piece of memory with the contents of an object of type Color.
Thus, you can just delete that memory through that pointer:
delete color;
Now, in this case, *color wouldn't be too useful: you are referencing the MEMORY that the object occupies, which isn't what you want.
Let's take another example: if you have a simple object, say an array of characters:
char *str = new char[200];
then the pointer str points to the instantiated object, and *str to the memory contents that the object occupies. In that case, the pointer itself isn't what you want: you are interested in the actual data stored in that memory block (i.e. a string of characters).
Thus, delete[] str; will delete the memory block that str points to. delete[] *str; won't make much sense.
so, if we try this with printf():
char *str = new char[200];
strcpy(str, "test");
printf("The variable's contents are: %s", str); // will print the string itself
printf("The variable's address is: %p", str); // will print the address of the string in memory
Here's a useful link regarding pointers, to clear some things out:
http://courses.washington.edu/css342/zander/css332/pointers.html
I need help in understanding when shall I use the following options
char *a = new char();
and
char *a = new char[sizeof(int)+1];
and how the respective memory freeing calls should be made?
Any time you use new T, you have to call delete on the resulting pointer afterwards.
Any time you use new T[n], you have to call delete[] on the resulting pointer afterwards.
And that's really all there is to it.
But note that you typically shouldn't use them at all.
If you need a string, don't allocate a char array. Just declare a std::string (without using new). If you need an array whose size is determined at runtime, don't allocate an array. Declare a std::vector (without using new).
The fist one allocates a single char. You delete it with:
delete a;
The second one allocates an array of chars. The length you have chosen is a little strange. You deallocate it with:
delete[] a;
Now... I hope you don't think you can put a stringified number in the second a (something like "123456", because you'll need many more bytes. Let's say at least 12 if an int is 32 bits. There is a funny formula to calculate the minimum length necessary. It's an approximation of the log10 https://stackoverflow.com/a/2338397/613130
To be clear, on my machine sizeof(int) == 4, but in an int I can put -2147483648 that is 10 digits plus the -, so 11 (plus the zero terminator)
None of the expressions you show make much sense.
Also, as a general rule, never use an explicit delete (leave that to smart pointers and collections), and try to avoid using any explicit new.
For simple strings with char elements, just use
std::string a;
This is an example of leaving the new-ing and delete-ing to a library class (which is strongly preferable), in this case std::string.
Include the <string> header to get a declaration of the std::string type.
char *a = new char();
This creates a pointer to a single initialized char.
char *a = new char;
Creates a pointer to a single uninitialized char.
char *a = new char[sizeof(int)+1];
Creates a dynamically allocated char array, of size sizeof(int)+1, i.e. an uninitialized c-string of size sizeof(int)+1. Probably 5 or 9, depending on sizeof(int).
char *a = new char[sizeof(int)+1]();
The same, but the string is initialized.
You need to explicitly free the memory with delete for a single char* and delete[] for the char array.
Another thing worth pointing out as well as the other answers is do not mix the two statements up - you should know whether you allocated a pointer or an array to char* c so that:
You call the correct delete/delete[] operator when cleaning up memory
You do not try accessing data beyond the pointer's scope.
For example, if you did:
// Create a pointer to a single char and set the value
char* c = new char();
*c = 'a';
// Access the pointer using array syntax
char tmp1 = c[0]; // Works, returns 'a'
char tmp2 = c[1]; // Illegal!
Because there are no safe-guards on pointers trying to access c[1] would do something, but in this context it will not return what you expect, it will most likely return memory stored after the char* c pointer or random memory.