all is not always what it seems.

I found out the hard way that there is a very big difference between a copy and a direct assignment .

char* a = new char();
char* b = new char();

cin.getline(a,10,'\n');

strcpy(b,a); //ok makes a SEPARATE copy

a=b; //This seems to cause the pointers to use the same memory location.

Is my assessment correct?
also, if b had data in it previously, does this cause a memory leak due to abandonment of the heap area formally pointed to by b? Will the statement delete [] b; recover it even after direct re-assignment?

Lines 1 and 2 only allocate one char of memory. Any attempt to use strcpy() on either pointer will normally cause memory corruption because strcpy() adds a '\0' to the end of the string that it copies. Line 4 will most definitely corrupt memory because you told getline() to accept up to 10 characters when in fact only 1 character was allocated.

Line 8: yes it causes both pointers to point to the same memory location, thus the memory allocated in line 1 is tossed into the bit bucket and a memory leak occurs.

also, if b had data in it previously, does this cause a memory leak due to abandonment of the heap area formally pointed to by b? Will the statement delete [] b; recover it even after direct re-assignment?

In the example you gave, you haven't used new[], therefore you shouldn't use delete[]

Perhaps you intended lines 1 and 2 to look more like this?

char* a = new char[11];
char* b = new char[11];

in which case, the use of delete[] would be correct.

In general, when you allocate memory with new, deallocate it with delete.
when you allocate memory with new[], deallocate it with delete[].

Lines 1 and 2 only allocate one char of memory. Any attempt to use strcpy() on either pointer will normally cause memory corruption because strcpy() adds a '\0' to the end of the string that it copies. Line 4 will most definitely corrupt memory because you told getline() to accept up to 10 characters when in fact only 1 character was allocated.

What you say makes perfect sense, but the way it operates is it takes the char* and auto-increments the pointer, resulting in it being recognized as a string with the added null.

I can get a correct size reading with strlen (a) whereas
sizeof a is unpredictable. strcpy() works reliably too!

Is this one of those "gray areas" in c++ ?

I your opinion, what would be the correct way to stuff the char* with input ? A c-style?

>>but the way it operates is it takes the char* and auto-increments the pointer
No it doesn't -- new operator does not do anything to the pointer.

sizeof operator is always predictable and returns the size of the object, not that the object contains. The size of a pointer is always a constant value regardless of what it points to. The size of a char array (not a pointer) is however much memory was allocated for the string.

char *ptr = "Hello World";
char array[] = "Hello World";

In the above, sizeof(ptr) will always be 4 (32-bit compilers) because that is that is how many bytes are needed to store the address. sizeof(array) however will be 12 because there are 11 characters plus the null terminator. Note that pointers and character arrays are not the same thing.

strlen() on the otherhand actually iterates through the memory address of the pointer and searches for the first null character then returns the length of the string. This will be the same for both examples I posted above.

>>I your opinion, what would be the correct way to stuff the char* with input ? A c-style?
Line 10 in the code you posted is ok, but you need to allocate memory as in Bench's example.

>Is this one of those "gray areas" in c++ ?
No, this is one of those undefined areas in C++. You did something wrong, and whether it works (for now) or breaks spectacularly is up to random chance.

>I your opinion, what would be the correct way to stuff the char* with input ?
It really doesn't matter as long as you don't store more than you allocate.

>>but the way it operates is it takes the char* and auto-increments the pointer
No it doesn't -- new operator does not do anything to the pointer.

I guess the way I wrote that wasn't clear.

I was referring to :

char * a = new char();//pointer to heap
cin.getline(a,10,'\n'); //this seems to auto-increment and add a null, which was fine for the application.

temp = a[0]; // this continues to work as advertised as well!

After the pointer was run through this function it was then recognized everywhere in the program as a string. Even the following works...it will print out the entire string! I was surprised.

cout << a;

As I see, this gets a thumbs down ?. This is junk, so I should use a c-style string to load the char *a ?

Tricky...

>After the pointer was run through this function it was then recognized
>everywhere in the program as a string. Even the following works...it will
>print out the entire string!
Run the following and examine the output. This is essentially what's happening with your example:

#include <iostream>

using namespace std;

int main()
{
  char left_buffer[] = "01234";
  char buffer[1];
  char right_buffer[] = "ABCDE";

  cin.getline ( buffer, 5 );
  cout<< left_buffer <<'\n'<< buffer <<'\n'<< right_buffer <<'\n';
}

Just because it happens to work doesn't mean it's not horribly broken.

Wow! That was interesting. Getline essentially "ate" the left buffer.
I suppose it was left buffer since it was allocated first. Everything uses the lowest address number available and works out from there?

So, the moral to the story is to preallocate pointers to avoid problems?
By changing buffer to [6] fixed the problem.

I was hoping that that char was dynamically allocated so that they didn't waste memory like arrays do. No free lunch -eh?

Edited 3 Years Ago by happygeek: fixed formatting

Comments
The moral of the story is use std::string like everyone else.

>I was hoping that that char* was dynamically allocated so that they didn't waste memory like arrays do.
Okay, but you still need to know how much to allocate. And when it comes to user input, you simply can't predict it. This is where std::strings are ideal because they grow dynamically even when using getline, so you don't have to play games with a static buffer and dynamic storage.

This article has been dead for over six months. Start a new discussion instead.