Memory allocation question in C++ - c++

int main() {
char** k;
k = new char*;
char* k1 = "abc";
char* k2 = "def";
*k = k1;
*(k + 1) = k2;
delete [] (k + 1);
}
Error: segmentation fault
Could someone explain why I get segmentation fault when freeing (k + 1)? I was able to free k with no problems.
ADD: In the answers it has been said that I can't delete [] (k + 1) since I haven't used new on it; But how do you explain the fact that cout<<*(k + 1)<<endl; printed correctly?

k = new char*;
This allocated storage for only a single char*.
*(k + 1) = k2;
This tries to pretend there are two char*s allocated. This may not be the site of the segfault, but it is the error.
delete [] (k + 1);
Here you're trying to delete[] something you did not new[], another error.
EDIT: Deep down, memory is allocated in large chunks, such as pages. So when you allocate a small bit of storage, it's very likely that the memory around it is also valid. It's still very invalid to access it, though.
More to the point, when you say something like new char*, this turns into a call to operator new(sizeof(char*)). Let's say the OS allocates a new 4K page of physical RAM for that at address 0x12340000. The memory manager needs a small structure in there to keep track of the block, something like:
struct mem_block_info {
void* next_block;
size_t block_size;
};
So it puts this structure at 0x12340000. Immediately after that, it puts the storage you requested, so (assuming this is a 32-bit machine) it returns a pointer of 0x12340008, since sizeof(void*) == sizeof(size_t) == 4. Then it needs to put a header after your storage to track the unused part of that 4K page, so it doesn't waste memory by allocating another 4K page when you want another char*. That header goes at the address right past the end of your allocated block, 0x1234000C. Once the dust settles, that new char* has put this in memory:
Address Data
0x12340000 0x00000000
0x12340004 0x00000001
0x12340008 uninitialized; could be anything
0x1234000C 0x00000000
0x12340010 0x00000FF4
The null pointers indicate the end of the allocated and free block linked lists.
So when you do:
*(k + 1) = k2;
k + 1 == 0x1234000C is the next_block pointer for the free block, and you just overwrote it with an invalid value (the address of a string in read-only memory, most likely). This does not immediately cause a segmentation fault, but when the memory manager tries to traverse the free block list, it will wind up looking at that string and misinterpreting it as a block header, then going to the next_block from there which is an invalid address, and boom, segfault.

One can only delete exactly what is returned from new, and same applies to new[] and delete[].
It is Undefined Behavior to pass any address to delete which was not returned by new.
Here is the quote from the C++ Standard.
§ 3.7.4.2-3
If a deallocation function terminates by throwing an exception, the behavior is undefined. The value of the first argument supplied to a deallocation function may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call has no effect. Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(std::size_t) or operator new(std::size_t, const std::nothrow_-t&) in the standard library, and the value supplied to operator delete[](void*) in the standard library shall be one of the values returned by a previous invocation of either operator new[](std::size_t) or operator new[](std::size_t, const std::nothrow_t&) in the standard library.

k + 1 isn't created using new[]. How can you then delete[] it?
They always come in pairs.

You can delete only the exact pointers returned by new. Everything else is illegal.

Related

Can't delete char array using cpp [duplicate]

int main() {
int* i = new int(1);
i++;
*i=1;
delete i;
}
Here is my logic:
I increment I by 1, and then assign a value to it. Then I delete the I, so I free the memory location while leaking the original memory. Where is my problem?
I also tried different versions. Every time, as long as I do the arithmetics and delete the pointer, my program crashes.
What your program shows is several cases of undefined behaviour:
You write to memory that hasn't been allocated (*i = 1)
You free something that you didn't allocate, effectively delete i + 1.
You MUST call delete on exactly the same pointer-value that you got back from new - nothing else. Assuming the rest of your code was valid, it would be fine to do int *j = i; after int *i = new int(1);, and then delete j;. [For example int *i = new int[2]; would then make your i++; *i=1; valid code]
Who allocates is who deallocates. So you should not be able to delete something you did not new by yourself. Furthermore, i++;*i=1; is UB since you may access a restricted memory area or read-only memory...
The code made no sense . I think You have XY problem. If you could post your original problem there will be more chance to help you.
In this case you need to have a short understanding how the heap memory management works. in particular implementation of it, when you allocate an object you receive a pointer to the start of the memory available to you to work with. However, the 'really' allocated memory starts a bit 'earlier'. This means the allocated block is a bit more than you have requested to allocate. The start of the block is the address you have received minus some offset. Thus, when you pass the incremented pointer to the delete it tries to find the internal information at the left side of it. And because your address is now incremented this search fails what results in a crash. That's in short.
The problem lies here:
i++;
This line doesn't increment the value i points to, but the pointer itself by the number of bytes an int has (4 on 32-bit platform).
You meant to do this:
(*i)++;
Let's take it step by step:
int* i = new int(1); // 1. Allocate a memory.
i++; // 2. Increment a pointer. The pointer now points to
// another location.
*i=1; // 3. Dereference a pointer which points to unknown
// memory. This could cause segmentation fault.
delete i; // 4. Delete the unknown memory which is undefined
// behavior.
In short: If you don't own a piece of memory you can't do arithmetic with it neither delete it!

What does "(new Type [n]) + 1" returns?

By referring to http://www.cplusplus.com/doc/tutorial/dynamic/, it is said that the new operator returns a pointer to the beginning of the new block of memory allocated. Let's assume again that any pointer has the feature of pointer arithmetic, which can make it true that p + 1 points to the next position in memory if p is a pointer.
Based on the above assumptions, I have tried the following block,
#include <iostream>
using namespace std;
int main(){
int * ptr = (new int [4]) + 1;
ptr[3] = 2;
cout << ptr[3] << endl;
/*Before delete the dynamic allocated memory,
it should be necessary to let ptr point to the
beginning of it, add one line to do that:
--ptr;*/
delete [] ptr;
}
I expected that ptr[3] should goes beyond the range of newly allocated memory. However, the result still give 2. Why the pointer arithmetic become useless? Or is it really new Type returns an object of *Type?
Thanks for any help.
I expected that ptr[3] should goes beyond the range of newly allocated memory.
It does indeed. You need to be careful not to do that, since (as you've noticed) that's an error that often can't be detected. Dynamic analysis tools like valgrind can help diagnose these problems, but not perfectly.
However, the result still give 2.
That means that there happened to be accessible memory beyond the end of the array, so the invalid access couldn't be detected. Instead, it overwrote memory that didn't belong to the array - perhaps it was unused, or perhaps you've overwritten some other data, which will cause baffling errors later.
Why the pointer arithmetic become useless?
It's as useful as any pointer arithmetic. Pointer arithmetic can't detect the end of an array, so you get undefined behaviour if it takes you out of range.
Or is it really new Type returns an object of *Type?
new Type[] returns a Type* pointer to the allocated array. That behaves just like any other pointer, so adding one gives you a pointer to the second element.
delete [] ptr also gives undefined behaviour, since ptr no longer points to the start of an allocated array.
Going beyond boundary is undefined behavior.
You may get different results when compiled by differet compiler, different compilation flags, even running at different time. You computer may blow off and your monitor may burn.
Return a correct value is one of undefined behaviors too.
C/C++ allows you to assign/read values to/from out of bounds memory, as this is undefined behavior.
For instance, this is valid code:
int *array = new int[10];
array[10] = 5;
std::cout<<array[10];
However, doing this you could damage other data structures, if they happen to have memory allocated adjacent to your array.
int * ptr = new int [4];
will point to ptr[0], so
int * ptr = (new int [4]) + 1;
will pont to ptr[1] and you will not be able to free ptr unless you do something like delete (ptr--);

Usage of number object in malloc

I am new to programming and I am trying to understand the difference between
A = (char * ) malloc(sizeof(char)*n);
and
A = (char * ) malloc(sizeof(char));
or
A = new char [n];
and
A = new char;
What is the default memory that a compiler is allocating to this pointer, when I do not specify the number of objects of particular data type.
Also when I declare
A = new char [n];
cout << A[n+1];
it does not give me a segmentation fault.
Should It not give segmentation fault because I am trying to access memory beyond what has been allocated for the Array.
Memory is not "allocated to this pointer", it's allocated and then you get a pointer to the memory.
This:
char *a = malloc(sizeof(char) * n);
is the same as
char *a = malloc(n);
since sizeof(char) is always 1. They both allocate space for n characters worth of data, and return a pointer to the location where the first character can be accessed (or NULL on failure).
Also, the casts are not needed in C, you should not have any.
Since sizeof(char) is 1, the second call is equivalent to:
char *a = malloc(1);
which means it allocates a memory block of size 1. This is of course distinct from the pointer to that memory block (the value that gets stored in the pointer variable a). The pointer is most likely larger than 1 char, but that doesn't affect the size of the block.
The argument to malloc() specifies how many chars to allocate space for.
I ignored the new usage, since that is C++ and the question is tagged C.
A = (char * ) malloc(sizeof(char)*n);
This allocates space for n characters.
A = (char * ) malloc(sizeof(char));
This allocates memory for 1 character.
Every call to malloc allocates memory in the heap.
The other code is C++, and it's exactly the same, except that it will use stack memory if A is a local variable. Accessing A[n+1] may or may not yield a segfault. A[n+1] can reference a memory address that you are allowed to use. Segfault happens when you go out of the region of memory you can access, and the way it works is that there is a "red zone" from which it is considered you accessed invalid memory. It may be the case that A[n+1] just isn't "invalid enough" to trigger a segfault.
allocate space for N characters (N should be some positive integer value here)
char *ma = (char * ) malloc(N);
char *na = new char [N];
don't forget to release this memory ...
delete [] na;
free(ma);
allocate space for a single character
char *mc = (char * ) malloc(sizeof(char));
char *nc = new char;
Now, as the others have pointed out, you tagged this C, but half your code is C++. If you were writing C, you couldn't use new/delete, and wouldn't need to cast the result of malloc.
Oh, and the reason you don't get a segmentation fault when you read off the end of your array is that this is undefined behaviour. It certainly could cause a SEGV, but it isn't required to check, so may appear to work, at least some of the time, or fail in a completely different way.
Well, the compiler doesn't allocate memory for the data. Only the pointer which is either 4 or 8 bytes depending on your architecture.
There is no difference between the first two and the last two in terms on functionality. Most C++ libraries I've seen use malloc internally for new.
When you run the code to allocate n characters and you print out the n + 1th character, you aren't getting a segmentation fault most likely because n isn't a multiple of some number, usually 8 or 16. Here's some code on how it might do that:
void* malloc(size_t size) {
if (size & 0x7 != size)
size = size & 0x7 + 1;
return _malloc(size);
}
So, if you requested, say, 5 bytes, malloc would actually allocate, with that code, 8 bytes. So, if you request the 6th byte (n + 1), you would get garbage, but it is still valid memory that your program can access.

Why does a large static array give a seg-fault but dynamic doesn't? (C++)

The following code gives me a segmentation fault:
bool primeNums[100000000]; // index corresponds to number, t = prime, f = not prime
for (int i = 0; i < 100000000; ++i)
{
primeNums[i] = false;
}
However, if I change the array declaration to be dynamic:
bool *primeNums = new bool[100000000];
I don't get a seg-fault. I have a general idea of why this is: in the first example, the memory's being put on the stack while in the dynamic case it's being put on the heap.
Could you explain this in more detail?
bool primeNums[100000000];
used out all your stack space, therefore, you will get segmentation fault since there is not enough stack space to allocate a static array with huge size.
dynamic array is allocated on the heap, therefore, not that easy to get segmentation fault. Dynamic arrays are created using new in C++, it will call operator new to allocate memory then call constructor to initialize the allocated memory.
More information about how operator new works is quoted from the standard below [new.delete.single]:
Required behavior:
Return a nonnull pointer to suitably aligned storage (3.7.3), or else throw a bad_alloc exception. This requirement is binding on a replacement version of this function.
Default behavior:
— Executes a loop: Within the loop, the function first attempts to allocate the requested storage. Whether the attempt involves a call to the Standard C library function malloc is unspecified.
— Returns a pointer to the allocated storage if the attempt is successful. Otherwise, if the last argument to set_new_handler() was a null pointer, throw bad_alloc.
— Otherwise, the function calls the current new_handler (18.4.2.2). If the called function returns, the loop repeats.
— The loop terminates when an attempt to allocate the requested storage is successful or when a called new_handler function does not return.
So using dynamic array with new, when there is not enough space, it will throw bad_alloc by default, in this case, you will see an exception not a segmentation fault, when your array size is huge, it is better to use dynamic array or standard containers such as vectors.
bool primeNums[100000000];
This declaration allocates memory in the stack space. The stack space is a memory block allocated when your application is launched. It is usually in the range of a few kilobyes or megabytes (it depends on the language implementation, compiler, os, and other factors).
This space is used to store local and static variables so you have to be gentle and don't overuse it. Because this is a stack, all allocations are continuos (no empty space between allocations).
bool *primeNums = new bool[100000000];
In this case the memory is allocated is the heap. This is space free where large new chucks of memory can be allocated.
Some compilers or operating systems limit the size of the stack. On windows the default is 1 MB but it can be changed.
in the first case you allocate memory on stack:
bool primeNums[100000000]; // put 100000000 bools on stack
for (int i = 0; i < 100000000; ++i)
{
primeNums[i] = false;
}
however this is allocation on heap:
bool *primeNums = new bool[100000000]; // put 100000000 bools in the heap
and since stack is (very) limited this is the reason for segfault

Pointers pointing contiguous memory

Consider the following code
struct foo
{
const int txt_len;
const int num_len;
char * txt;
int * num;
foo(int tl, int nl): txt_len(tl), num_len(nl)
{
char * tmp = new char[txt_len * sizeof(char) + num_len * sizeof(int)];
txt = new (tmp) char [txt_len * sizeof(char)];
num = new (tmp + txt_len * sizeof(char)) int[num_len * sizeof(int)];
// is this the same as above?
// txt = tmp;
// num = (int *) (tmp + txt_len * sizeof(char));
}
~foo()
{
delete[] txt; // is this the right way to free the memory?
}
};
I want *txt and *num to be contiguous, is that the best way to do it?
also is there any difference between placement new and pointer arithmetic? which one should I use?
If you want a contiguous block of memory, you have to allocate it whole with a single call to operator new[] or malloc() or similar. Multiple calls to these functions do not guarantee any contiguity of allocated blocks whatsoever. You may allocate a big block and then carve parts from it as needed.
And you should delete and free() all blocks previously allocated with new and malloc(), otherwise you'll leak memory and probably make your program unstable (it will fail to allocate more memory at some point) and exert unnecessary pressure on memory in the OS, possibly slowing down other programs or making them unstable as well.
Placement new, however, does not actually allocate any memory. It simply constructs an object at the specified location and so you don't need to free that memory twice.
One problem that I see in your code is that it doesn't align ints. On some platforms reading or writing integers bigger than 1 byte from/to the memory must be aligned and if it's not, you can either read/write values from/to wrong locations or get CPU exceptions leading to termination of your program. The x86 is very permissive in this regard and won't mind, though may tax you with degraded performance.
You'll need to put the int data first, due to the alignment issues. But we can't then do delete num[] as the type is wrong - it must be cast to a char* before deleting.
char * tmp = new char[num_len * sizeof(int) + txt_len * sizeof(char)];
num = new (tmp) int[num_len];
txt = new (tmp + num_len * sizeof(int)) char [txt_len];
(This makes liberal use of the fact that sizeof(char)==1)
You might be tempted to do delete[] num, but num is of type int*, and it was new'ed as a char*. So you need to do;
delete[] (char*) num;
This is the same as long as you use POD types. And your delete is fine.
However, as David's comment states, you need to consider alignment problems.
Placement new is mostly use when you want to call constructor of class/struct on some preallocated memory blocks.
But for native types it makes no different to use placement new & pointer arithmetic.
Please correct me if I was wrong.
If txt and num always point to int and char, other built in types or other types not requiring construction, then no. You don't need placement new.
If on the other hand you were to change one of them to a class which requires construction, i.e. changes txt to type std::string, then using placement new is necessary.
Placement new allows you to call the constructor, building, if you like, the object at that address. Built in types have default constructors that do nothing if your not initializing.
In both cases you need to do pointer arithmetic, just one way you store the answer in a pointer, the other you pass the answer to placement new which gives it back to you for storage in the pointer, and then calls the constructor.