Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why must a pointer to a char array need strcpy to assign characters to its array and double quotes assignment will not work?

The first example does not work when you go to delete the pointer. The program either hangs when I add the null terminator or without it I get:

Debug Assertion Failed Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) from Visual Studio 2008

//Won't work when deleting pointer:
    char *at = new char [3];
    at = "tw"; //   <-- not sure what's going on here that strcpy does differently
    at[2] = '\0'; // <-- causes program to hang
    delete at;

//Works fine when deleting pointer:
    char *at = new char [3];
    strcpy(at,"t");
    at[1] = 'w';
    at[2] = '\0';
    delete at;

So what's going on when I use double quotes instead of strcpy? Both of them will cout the string perfectly and debugger does not show anything different.

like image 904
Omar Avatar asked Oct 16 '09 12:10

Omar


2 Answers

When you do

char *at = ...;

at = "hello";

You're basically overwriting the pointer value (i.e., the address of the memory allocated for you by new[]) with the address of a static constant string. This means that when you later delete that memory, you're passing delete a pointer not previously returned by new.

That is a bad thing to be doing.

In C and C++, assignments to pointers typically don't do anything to the memory being pointed at, they change the pointer itself. This might be confusing if you're used to a language where strings are more of "first class citizens".

Also, you should use delete[] if you used new[].

like image 59
unwind Avatar answered Nov 15 '22 19:11

unwind


Because a char* isn't a string. It's just a pointer to some character, with the convention that there might be more characters to follow and that after the last one there is a '\0'.

A string 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. The result is that

at = "tw";

means, the pointer at is assigned the address of the first character in the string literal "tw". By this, it will lose its old value. Since this was the address of a dynamically allocated character array, you are leaking this array.

When you later assign to a character in the array at now points to, you are assigning a new value to some character in the string literal. That's invoking undefined behavior and the program hanging or crashing immediately is probably the best that could happen to you when you do this. (On many platforms you're writing to read-only memory doing so.)

Later you pass at to delete[] (and not delete, since you called new[], not new). In doing so, you pass it the address of the string literal, instead of the allocated character array. This will, of course, mess up the heap manager. (VC's runtime library catches this in Debug mode.)

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.

Let me add this: As a beginner in C++, you should use std::string, rather than C strings. That does all the dirty work for you and has sane semantics.

like image 35
sbi Avatar answered Nov 15 '22 19:11

sbi