C++ char allocation - c++

I'm using something like this:
char* s = new char;
sprintf(s, "%d", 300);
This works, but my question is why?
When I try to delete it I get an error so this produces a memory leak.

It "works" because sprintf expects a char* as its first argument, and that what's you are giving him.
However, you really just allocated one char so writing more than one char to it is undefined behavior. It could be that more than one byte gets allocated depending on... the compiler, the host architecture, and so on but you can't rely on it. Actually, anything could happen and you don't want to base your code on such assumptions.
Either allocate more space for your string buffer, or better use a more "modern" approach. In your case it could be something like:
std::string s = std::to_string(300);
// Or, C++03
std::string s = boost::lexical_cast<std::string>(300);
(We are not talking about performance here, but the initial code being incorrect, we could hardly compare anyway).
As an added bonus, this code doesn't leak any memory because std::string takes care of freeing its internal memory upon destruction (s being allocated on the stack, this will happen automatically when it goes out of scope).

You're creating a one char buffer, then write to it with four chars ("300\0") [don't forget the string termination as I did] so the '3' goes into your allocated memory and the '0' and '0' and the '\0' goes to the next memory positions... that belong to someone else.
C++ does not do buffer overrun checking... so it works until it doesn't...

Related

How can the strcpy function copy a large string into a smaller string?

In the following code it seems that I can copy an entire large string into a small string.
So my question, how does that work? I only allocated 2 characters to str1, but it was able to store a longer string.
Does this mean that strcpy is modifying memory on the stack that doesn't belong to us?
Can arrays on the stack dynamically grow after its initialization?
str1 size has not changed after the copy operation but it is holding a longer string. Thats bonkers!
I paste the code just make my point clearer:
char str1[2] = "a";
char str2[100] = "abcd";
cout<<"Before copying"<<endl;
cout<<"str1: "<<str1<<" size: "<<sizeof(str1)<<endl;
cout<<"str2: "<<str2<<" size: "<<sizeof(str2)<<endl;
strcpy(str1, str2);
cout<<"After copying"<<endl;
cout<<"str1: "<<str1<<" size: "<<sizeof(str1)<<endl;
cout<<"str2: "<<str2<<" size: "<<sizeof(str2)<<endl;
So my question, how does that work?
Poorly. It doesn't do any checks whatsoever to confirm that the operation you're doing makes sense. You're the one responsible for checking that (which obviously leads to bugs).
strcpy is generally just byte-copying loop. It will write the data into increasing addresses. As long as the memory you're writing to is "yours", after such copy printing the string will work just fine; the issue is what's actually in the memory you've overwritten.
Yes, and you're "lucky" that it didn't break the 2nd string. The requirements for strcpy ask you to provide adequate output storage.
Generally no, especially when it comes to arrays further up the stack.
It's not the string size, it's the static array size obtained with sizeof. What you might be thinking about is strlen.
All in all, never use C functions in C++ unless you have a very good reason to, use std::string and none of those issues will happen. In fact, that's what your compiler could have told you:
Error C4996 strcpy: This function or variable may be unsafe. Consider using strcpy_s instead.
If you listened, here's what you could get when running the program:
Those additional checks, however, are not a replacement for a well-written, well behaved program.

Default dynamic memory size

I have the following code:
#include <iostream>`
using namespace std;
int main() {
char* data = new char;
cin >> data;
cout << data << endl;
return 1;
}
When I type in a char* of 26 ones as a string literal, it compiles and prints it. But when I do 27 ones as data, it aborts. I want to know why.
Why is it 27?
Does it have a special meaning to it?
You're only allocating one character's worth of space. So, reading in any data more than that is overwriting memory you don't own, so that's undefined behavior. Which is what you're seeing in the result.
You'd have to look into specific details under the hood of your C++ implementation. Probably the implementation of malloc, and so on. Your code writes past the end of your buffer, which is UB according to the C++ standard. To get any idea at all of why it behaves as it does, you'd need to know what is supposed to be stored in the 27 or 28 bytes you overwrote, that you shouldn't have done.
Most likely, 27 ones just so happens to be the point at which you started damaging the data structures used by the memory allocator to track allocated and free blocks. But with UB you might find that the behavior isn't as consistent as it first appears. As a C++ programmer you aren't really "entitled" to know about such details, because if you knew about them then you might start relying on them, and then they might change without notice.
Your dynamically allocating one byte of storage. To allocate multiples, do this:
char* data = new char[how_many_bytes];
When you use a string literal, that much stack space is allocated automatically. When you allocate dynamically, you have to get the number of bytes right or you will get a segfault.
This is just Undefined Behavior, a.k.a. "UB". The program can do anything or nothing. Any effect you see is non-reproducable.
Why is it UB?
Because you allocate space for a single char value, and you treat that as a zero-terminated string. Since the zero takes up one char value there is no (guaranteed) space for real data. However, since C++ implementations generally do not add inefficient checking of things, you can get away with storing data in parts of memory that you don't own – until it crashes or produces invalid results or has other ungood effect, because of the UB.
To do this correctly, use std::string instead of char*, and don't new or delete (a std::string does that automatically for you).
Then use std::getline to read one line of input into the string.

Playing with char array

Is that safe to do something like this:
char* charArray = new char[10];
strcat(charArray, "qwertyuiop");
charArray[3] = '\0';
delete [] charArray;
Will everything be deleted? Or that what is after \0 won't be? I don't know if I'm leaving garbage.
EDIT: should be strcpy
Apart from the fact that new[] for POD-types does not zero-initializes the array, and strcat would write the terminating '\0' past the end of the allocated area, everything looks fine: in particular, delete will delete the entire block.
The reason for writing past the end of the allocated block is that the 10-character string "qwertyuiop" requires 11 bytes to store.
If you wanted to write strcpy instead of strcat, then that is safe and correct. But it seems you've a misconception about delete [] charArray. It doesn't delete characters, it deletes the memory pointed to by charArray. The memory even after delete [] charArray might contain those characters, it is not guaranteed though.
However, if you really wanted to write strcat, and it is not a typo, then your code invokes undefined behavior, because charArray contains garbage to which strcat will attempt to concatenate the second string.
The delete[] releases the memory allocated after destroying the objects within (which diesn't do anything for char). It doesn't care about the content i.e. it will deallocate as many objects as were allocated.
Note that the use of strcat() depends on a null character to find the end of the string and that the memory returned from new char[n] is uninitialized. You want to start of with
*charArray = 0;
... and you might want to consider strncat() or, yet better, not use this at all but rather use std::string.
The delete[] statement does not know anything about what is stored in the buffer (including whether it is a string or not), so it will delete all 10 characters. However, your strcat call is overflowing the end of the array (since C strings have a zero byte as terminator), which might break deletion on your platform and is not safe in general.
No, this is fine, the whole array is deleted. delete doesn't look at what the pointer you give it points to. As long as you match new with delete, and new[] with delete[], the right amount of memory will be freed.
(But do consider using std::string instead of char arrays, that'll avoid a lot of bugs like the one you have there writing past the end of your array.)

C++ memory leaks: are dynamically created arrays removed on leaving a function call?

So I have a function that creates a dynamic array, I then delete the array before I leave the function (as I thought I am supposed to), however I am getting a 'Heap Corruption Detected' warning in VS2008. If I remove the line that deallocates the memory everything works fine:
void myFunc()
{
char* c = new char[length];
memset(c, 0, length);
//.. do somsething with array
delete[] c; //this line throws an error??
}
Thanks for any advice
Most likely you are doing something else bad (like under/overflowing your buffer) and corrupting the heap at that point, but it isn't detected until you call delete[] and try to interpret the now corrupted heap structures.
Post the 'do something' section if you need more assistance.
I think you have a problem with your //.. do something with array code (or even some other code) since the rest of what you have is okay.
Often, memory arena corruption is only detected when freeing the memory which is probably why removing the line seems to fix it.
But rest assured, the arena is still corrupted whether or not you're detecting it. You need to fix it.
One way this might happen is if your memory allocation routines actually allocate extra bits before and possibly after what you're given. For example, if you ask for 1024 bytes, what might actually be allocated from the heap is a 1040-byte block of which you're given the address of the 16th byte. This gives the arena manager 16 bytes at the start to store housekeeping information (including a sentinal value at the very start of it).
Then, when the block is deleted, the arena manager knows that its housekeeping is in the 16 bytes before the address you're trying to free and can check the sentinal value (or all the sentinals in the arena or just the ones on either side of the one you're freeing - this is all implementation detail) to make sure they're unchanged. If they have been changed, that's detected as corruption.
As I said earlier, the corruption couuld be caused by your //.. do something with array code or it could be somewhere totally different - all that matters is that the arena is being trashed.
You're probably underflowing the buffer, actually - the VC heap (and most heap implementations) keep book-keeping information immediately before the allocation they hand out. It includes some data validation (sentinel bytes, etc), which is it doesn't pass, this error is thrown.
Every time you allocate memory using new, you will need to free that memory using a matching delete. The code you quote should work.
C++ memory manager implementations typically interleave their control data structures with areas of memory you allocate. C++ does not bounds-check arrays for you. If your code writes data off the end or before the start of an array, this will corrupt the heap. It is very likely that this is what is happening here. Carefully examine the code that performs work on the array.
First, to answer the title, no dynamically allocated memory (with new, malloc, etc) is not freed when function exits. You are responsible for freeing it.
Second, just an advice that might help you debug your problem.
One great option is to use a free tool from Microsoft, called Application Verifier. It's a great tool to have in your toolbox, it's really great at helping you finding bugs in your applications.
Another option, not involving use of other tools would be, instead of your allocated array, you could try using std::vector, it might help detecting your heap corruption in debug mode. It has a huge amount of various checks in debug mode, which would likely cause it to break into debugger at the right time. Here's what you could try:
{
const size_t size_of_array = 64;
// use constructor with size and value
// do _not_ use memset on this object
std::vector<char> your_array(size_of_array, 0);
// do something here with it e.g.:
snprintf(&your_array[0], your_array.size(), "hello");
// do whatever you do with your array
// use debug build and run it under debugger,
// likely you will spot your problem pretty soon
// no need to delete anything here
}
This warning means you probably wrote to memory you don't own, perhaps by overrunning a buffer, freeing memory more than once, or forgetting to initialize a pointer before using it.
Good luck
delete does not throw. This is guaranteed. If you are allocating for some "length", and if you are using the entire char array without having '/0' at the end, then you would get this error. Eg:
char* arr = new char[5];
strcpy(arr, "Jagan");
delete[] arr;
Instead, allocate arr of length 6 in this case.

Character arrays question C++

Is there any difference between the below two snippets?
One is a char array, whereas the other is a character array pointer, but they do behave the same, don't they?
Example 1:
char * transport_layer_header;
// Memory allocation for char * - allocate memory for a 2 character string
char * transport_layer_header = (char *)malloc(2 * sizeof(char));
sprintf(transport_layer_header,"%d%d",1,2);
Example 2:
char transport_layer_header[2];
sprintf(transport_layer_header,"%d%d",1,2);
Yes, there is a difference. In the first example, you dynamically allocate a two-element char array on the heap. In the second example you have a local two-element char array on the stack.
In the first example, since you don't free the pointer returned by malloc, you also have a memory leak.
They can often be used in the same way, for example using sprintf as you demonstrate, but they are fundamentally different under the hood.
The other difference is that your first example will corrupt data on the heap, while the second will corrupt data on the stack. Neither allocates room for the trailing \0.
The most important difference, IMO, is that in the second option transport_layer_header is a const pointer (you can't make it point to a different place), where as in the first option - you can.
This is ofcourse in addition to the previous answers.
Assuming you correct the "no room for the null" problem, i.e. allocate 3 bytes instead of 2, you would normally only use malloc() if you need dynamic memory. For example, if you don't know how big the array is going to be, you might use malloc.
As pointed out, if you malloc() and don't later free the memory then you have a memory leak.
One more point: you really should check the return value of malloc() to ensure you got the memory. I know that in Solaris malloc() never fails (thought it may sleep -- a good reason not to call it if you don't want your process going to sleep, as noted above). I assume that on Linux malloc() could fail (i.e. if there is not enough memory available). [Please correct me if I'm wrong.]