Why does this C++ program cause a memory leak? - c++

Consider the following piece of code:
char* str1 = new char [30];
char* str2 = new char [40];
strcpy(str1, "Memory leak");
str2 = str1;
delete [] str2;
delete [] str1;
Why does the above program cause a memory leak? How do I avoid this?

The above doesn't just lead to a memory leak; it causes undefined behavior, which is much, much worse.
The problem is in the last three lines:
str2 = str1;
delete [] str2;
delete [] str1;
If we ignore this first line, then the last two lines correctly reclaim all the memory allocated in this function. However, this first line sets str2 to point to the same buffer as str1. Since str2 is the only pointer in the program to the dynamic memory it references, this line leaks the memory for that buffer. Worse, when you then execute the next two lines to clean up the two pointers, you delete the same block of memory twice, once through str2 and once through str1. This leads to undefined behavior and often causes crashes. Particularly malicious users can actually use this to execute arbitrary code in your program, so be careful not to do this!
But there's one higher-level issue to take into account here. The whole problem with this setup is that you have to do all your own memory management. If you opt to use std::string instead of raw C-style strings, then you can write the code like this:
string str1 = "Memory leak"; // Actually, it doesn't. :-)
string str2;
str2 = str1; // Okay, make str2 a copy of str1
// All memory reclaimed when this function or block ends
Now, there's no need to explicitly manage the memory, and you don't have to worry about buffer overruns or double-frees. You're saved by the magic of object memory allocation.

Because you're deleting str1 (the memory it points to) twice and you don't delete the memory allocated under where str2 was first pointing to.
EDIT:
I'm not sure what you're trying to achieve.
char* str1 = new char [30];
// str1 = 0x00c06810; (i.e.)
char* str2 = new char [40];
// str2 = 0x00d12340; (i.e.)
strcpy(str1, "Memory leak");
// delete [] str2; should be here
str2 = str1;
// now str2 == str1, so str2 = 0x00c06810 and str1 = 0x00c06810
// deleting 0x00c06810
delete [] str2;
// deleting 0x00c06810 once again
delete [] str1;
// 0x00d12340 not deleted - memory leak
If you want that assignment (str2 = str1) then delete str2 first.

You assign str1 pointer to str2 pointer, so delete[]str1 and delete[]str2 free only memory pointed by str1 (str2 points to the same memory). You need to free str2 memory before loosing pointer to it (before assigning str1 to str2)
The correct way is
char* str1 = new char [30];
char* str2 = new char [40]; //or just don't allocate this if You don;t need it
strcpy(str1, "Memory leak");
**delete [] str2;**
str2 = str1;
delete [] str1;

make pointers to be const pointers
The problem is that you allocate memory for two arrays, you get two pointers, then you overwrite address of the second array with address of first array. So you try to free memory of the first array

Every object needs to be pointed-at in the memory.
The pointers keep track of where the data is (remember that your RAM memory is HUGE compared to the little array).
So in your case, you're losing the second array's place in memory. So there's an array lost somewhere in memory that you can't get to.
When you do str2 = str1; str2 points now to the block of memory that str1 pointed to. So there's nothing left to point at the second array.

Related

Can you copy data to `char*` pointer without allocating resource first?

I have seen an example here: http://www.cplusplus.com/reference/string/string/data/
...
std::string str = "Test string";
char* cstr = "Test string";
...
if ( memcmp (cstr, str.data(), str.length() ) == 0 )
std::cout << "str and cstr have the same content.\n";
Question> How can we directly copy data into the location where the pointer cstr pointed to without explicitly allocating space for it?
memcmp is comparing the content of memory pointed to by the two pointers. It does not copy anything.
[EDIT] The question was edited to add a concrete question. The answer is: you need the pointer to point to memory allocated one way or another if you want to copy data there.
How can we directly copy data into the location where the pointer cstr pointed to without explicitly allocating space for it?
You cannot, using an initialisation from a character string literal.
That memory will be placed in the static storage section of your program, and writing there is calling undefined behaviour (merely an exception in your particular compilers implementation).
lets assume that you used memcpy(cstr,x,...) instead of memcmp.
You use phrase 'without allocating resource first'. This really has no meaning.
For memcpy to work cstr must point at valid writable memory.
so the following work
char *cstr = new char[50];
char cstr[50];
char *cstr = malloc(50);
The following might work but shouldnt
char *cstr = "Foo"; // literal is not writable
This will not
char *cstsr = null_ptr;
char *cstrs; // you just might get lucky but very unlikely

difference between char [] and char* when doing strcpy

I have the following code, I wonder what is the difference between the implementation of str2 and str3, they both give the same results, which one is more prone to errors?
EDIT: when I was testing the representation of str2, I have found that one time my code crashed because str2 was a bad pointer!
/* strcpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[] = "Sample string";
char str0[] = "Sample String and more";
char* str2;
str2 = new char[40];
char str3[40];
strcpy (str2,str1);
strcpy (str3,str1);
strcpy (str2,str0);// crash happened here str2 is bad pointer!!!
printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
delete str2;
return 0;
}
Aside from the fact that str2 is a pointer whereas str3 is an array (and a pointer is a bit more trickier to use, since you may forget to delete it etc), there is another issue: the memory allocated for str2 is on the free space, via operator new. This is a slow operation. In contrast, str3 has automatic storage duration, and most often its memory is allocated on the stack, which is much faster. So in performance critical code this may make a difference.

Segmentation Fault in deleting char pointer

I'm posting two fragments here.
The first one is giving me Segmentation Fault on deallocating the memory. Second one is working fine.
1)
int main()
{
char* ch = new char;
ch = "hello";
cout << "\n " << ch << endl;
delete[] ch; ////OR delete ch; ---> have tried both
return 0;
}
2)
int main()
{
char* ch = new char;
cin >> ch;
cout << "\n " << ch << endl;
delete[] ch; ///OR delete ch /// Both are working fine....
return 0;
}
Could anybody please tell me why the first one is failing with Segmentation Fault and second one is working fine with both delete and delete[]. Because to me both the program seems to same.
new char generates exactly 1 character (not an array of 1 character, use new char[1] for that)
so delete[] doesn't apply
in the first example, you overwrite your pointer to your allocated 1 character with a pointer to the character string "hello" - deleting this string (as it is static memory) will result in sesgfault
Edit
int main()
{
char* ch = new char; // ch points to 1 character in dynamic memory
ch = "hello"; // overwrite ch with pointer to static memory "hello"
cout<<"\n "<<ch<<endl; // outputs the content of the static memory
delete[] ch; // tries to delete static memory
return 0;
}
There are issues with both examples:
char* ch = new char;`
ch = "hello";`
The new returns an address that points to dynamically allocated memory. You must save this return value so that delete can be issued later. The code above overwrites this value with "hello" (a string-literal). You now have lost the value, and thus can not call delete with the proper value.
The second example, even though you say "works fine" is still faulty.
char* ch = new char;`
delete[] ch; ///OR delete ch /// Both are working fine....`
The wrong form of delete is used. You allocated with new, so you must deallocate with delete, not delete[]. It works this way: new->delete, new[]->delete[].
Unlike most other languages, if you go against the rules of C++, corrupt memory, overwrite a buffer, etc., there is no guarantee that your program will crash, seg fault, etc. to let you know that you've done something wrong.
In this case, you're lucky that simple types such as char* are not affected by you using the wrong form of delete. But you cannot guarantee that this will always work if you change compilers, runtime settings, etc.
There are a couple of problems with each, namely that you're only allocating a single character when you're trying to allocate a character array.
In the first example, you're also allocating a single character and then subsequently reassign the pointer to a character array - ch = "hello" will not copy the string, just reassign the pointer. Your call to delete[] will then attempt to delete a string that is not heap allocated, hence the seg fault. And you're also leaking the char you allocated, too.
In the first one, you change the pointer to point to a string literal:
ch = "hello";
String literals are static arrays, so mustn't be deleted.
The second is wrong for at least two reasons:
you allocate a single character, not an array; a single character would be deleted with delete not delete[]
cin>>ch will (most likely) read more than one character, but you've only allocated space for one.
Both of these cause undefined behaviour, which might manifest itself as a visible error, or might appear to "work fine" - but could fail when you least expect it.
To allocate an array, use new char[SIZE]; but even then, you can't prevent the user from giving too much input and overflowing the buffer.
Unless you're teaching yourself how to juggle raw memory (which is a dark art, best avoided unless absolutely necessary), you should stick to high-level types that manage memory for you:
std::string string;
string = "hello";
std::cout << string << '\n';
std::cin >> string;
std::cout << string << '\n';
there are several errors in your programs.
In the first program you are not deleting something dynamically allocated but the statically allocated string "hello". Infact when you execute ch="hello" you are not copying the string in the wrongly allocated buffer "new char" ( this new just allocates one char, not what you are looking for ) but you makes the pointer ch to point to the start of the string "hello" located somewhere in the non writable memory ( normaly that string are pointed directly into the executable ). So the delete operation is trying to deallocate something that cannot be deallocate. So the first program culd be rewritten like:
int main()
{
const char* ch = "hello";
cout<<"\n "<<ch<<endl;
return 0;
}
or like
int main()
{
char* ch = new char[strlen("hello")+1];
strcpy( ch, "hello");
cout<<"\n "<<ch<<endl;
delete[] ch; // with square brackets, it's an array
return 0;
}
Here's what's wrong with both snippets:
First snippet:
char* ch = new char; ch = "hello";
It's not legal to assign a string literal to a non-const char pointer .
Also, you re-assign the pointer immediately after you call new. The original value returned by new is now lost forever and can not be free for the duration of the program. This is known as a memory leak.
delete[] ch;
You try to deallocate the string literal. This crashes your program. You are only allowed to delete pointers that you get from new and delete[] pointers that you get from new[]. Deleting anything else has undefined behaviour.
Second snippet:
cout<<"\n "<<ch<<endl;
ch points to a single character, not a zero terminated char array. Passing this pointer to cout has undefined behaviour. You should use cout << *ch; to print that single character or make sure that ch points to a character array that is zero terminated.
delete[] ch;
You allocated with new, you must deallocate with delete. Using delete[] here has undefined behaviour.
Both are working fine....
"working fine" is one possible outcome of undefined behaviour, just like a runtime error is.
To answer the question, neither snippet is correct. First one crashes because you got lucky, second one appears to work because you got unlucky.
Solution: Use std::string.
You should use something like:
char* ch = new char[6] ;
strcpy(ch,"hello") ;
...
delete[] ch ;

exception of strcpy function in c++ console program

exception in strcpy();
void recid(string str,int *begin, int *end)
{
char *f,*str2;
const char c1[2]=":",c2[2]="-";
strcpy(str2,str.c_str());
f=strtok(str2,c1);
f=strtok(NULL,c2);
*begin=atoi(f);
f=strtok(NULL,c2);
*end=atoi(f);
}
could you help me to solve it?
str2 is an uninitialised pointer. strcpy does not allocate memory so is currently trying to write to an arbitrary address which you don't own and very likely isn't writable by your code.
You need to point str2 to valid memory before calling strcpy.
str2 = (char*)malloc(str.size()+1);
strcpy(str2,str.c_str());
You should also free the memory later in your program
free(str2); // cannot dereference str2 after this point
The problem is that you write in an uninitialized/random memory location by not initializing str2.
First solution:
str2 = new char[str.size() + 1];
strcpy(str2, str.c_str());
...
delete[] str2.
Second (better solution): Do not use pointers in your code unless you have to:
std::string str2 = str1;
Also, consider using std::ostringstream for tokenization into std::strings and converting to int.

Dynamic Memory Allocation

I have a small confusion in the dynamic memory allocation concept.
If we declare a pointer say a char pointer, we need to allocate adequate memory space.
char* str = (char*)malloc(20*sizeof(char));
str = "This is a string";
But this will also work.
char* str = "This is a string";
So in which case we have to allocate memory space?
In first sample you have memory leak
char* str = (char*)malloc(20*sizeof(char));
str = "This is a string"; // memory leak
Allocated address will be replaced with new.
New address is an address for "This is a string".
And you should change second sample.
const char* str = "This is a string";
Because of "This is a string" is write protected area.
The presumably C++98 code snippet
char* str = (char*)malloc(20*sizeof(char));
str = "This is a string";
does the following: (1) allocates 20 bytes, storing the pointer to that memory block in str, and (2) stores a pointer to a literal string, in str. You now have no way to refer to the earlier allocated block, and so cannot deallocate it. You have leaked memory.
Note that since str has been declared as char*, the compiler cannot practically detect if you try to use to modify the literal. Happily, in C++0x this will not compile. I really like that rule change!
The code snippet
char* str = "This is a string";
stores a pointer to a string literal in a char* variable named str, just as in the first example, and just as that example it won't compile with a C++0x compiler.
Instead of this sillyness, use for example std::string from the standard library, and sprinkle const liberally throughout your code.
Cheers & hth.,
In the first example, you dynamically allocated memory off the heap. It can be modified, and it must be freed. In the second example, the compiler statically allocated memory, and it cannot be modified, and must not be freed. You must use a const char*, not a char*, for string literals to reflect this and ensure safe usage.
Assigning to a char* variable makes it point to something else, so why did you allocate the memory in the first place if you immediately forget about it? That's a memory leak. You probably meant this:
char* str = (char*)malloc(20*sizeof(char));
strcpy(str, "This is a string");
// ...
free(str);
This will copy the second string to the first.
Since this is tagged C++, you should use a std::string:
#include <string>
std::string str = "This is a string";
No manual memory allocation and release needed, and assignment does what you think it does.
String literals are a special case in the language. Let's look closer at your code to understand this better:
First, you allocate a buffer in memory, and assign the address of that memory to str:
char* str = (char*)malloc(20*sizeof(char));
Then, you assign a string literal to str. This will overwrite what str held previously, so you will lose your dynamically allocated buffer, incidentally causing a memory leak. If you wanted to modify the allocated buffer, you would need at some point to dereference str, as in str[0] = 'A'; str[1] = '\0';.
str = "This is a string";
So, what is the value of str now? The compiler puts all string literals in static memory, so the lifetime of every string literal in the program equals the lifetime of the entire program. This statement is compiled to a simple assignment similar to str = (char*)0x1234, where 0x1234 is supposed to be the address at which the compiler has put the string literal.
That explains why this works well:
char* str = "This is a string";
Please also note that the static memory is not to be changed at runtime, so you should use const char* for this assignment.
So in which case we have to allocate memory space?
In many cases, for example when you need to modify the buffer. In other words; when you need to point to something that could not be a static string constant.
I want to add to Alexey Malistov's Answer by adding that you can avoid memory leak in your first example by copying "This is a string" to str as in the following code:
char* str = (char*)malloc(20*sizeof(char));
strcpy(str, "This is a string");
Please, note that by can I don't mean you have to. Its just adding to an answer to add value to this thread.
In the first example you're just doing things wrong. You allocate dynamic memory on the heap and let str point to it. Then you just let str point to a string literal and the allocated memory is leaked (you don't copy the string into the allocated memory, you just change the address str is pointing at, you would have to use strcpy in the first example).