C++ std::make_unique usage - c++

This is the first time I am trying to use std::unique_ptr but I am getting an access violation
when using std::make_unique with large size .
what is the difference in this case and is it possible to catch this type of exceptions in c++ ?
void SmartPointerfunction(std::unique_ptr<int>&Mem, int Size)
{
try
{
/*declare smart pointer */
//Mem = std::unique_ptr<int>(new int[Size]); // using new (No crash)
Mem = std::make_unique<int>(Size); // using make_unique (crash when Size = 10000!!)
/*set values*/
for (int k = 0; k < Size; k++)
{
Mem.get()[k] = k;
}
}
catch(std::exception& e)
{
std::cout << "Exception :" << e.what() << std::endl;
}
}

When you invoke std::make_unique<int>(Size), what you actually did is allocate a memory of size sizeof(int) (commonly 4bytes), and initialize it as a int variable with the number of Size. So the size of the memory you allocated is only a single int, Mem.get()[k] will touch the address which out of boundary.
But out of bounds doesn't mean your program crash immediately. As you may know, the memory address we touch in our program is virtual memory. And let's see the layout of virtual memory addresses.
You can see the memory addresses are divided into several segments (stack, heap, bss, etc). When we request a dynamic memory, the returned address will usually located in heap segment (I use usually because sometimes allocator will use mmap thus the address will located at a memory shared area, which is located between stack and heap but not marked on the diagram).
The dynamic memory we obtained are not contiguous, but heap is a contiguous segment. from the OS's point of view, any access to the heap segment is legal. And this is what the allocator exactly doing. Allocator manages the heap, divides the heap into different blocks. These blocks, some of which are marked "used" and some of which are marked "free". When we request a dynamic memory, the allocator looks for a free block that can hold the size we need, (split it to a small new block if this free block is much larger than we need), marks it as used, and returns its address. If such a free block cannot be found, the allocator will call sbrk to increase the heap.
Even if we access address which out of range, as long as it is within the heap, the OS will regard it as a legal operation. Although it might overwrite data in some used blocks, or write data into a free block. But if the address we try to access is out of the heap, for example, an address greater than program break or an address located in the bss. The OS will regard it as a "segment fault" and crash immediately.
So your program crashing is nothing to do with the parameter of std::make_unique<int>. It just so happens that when you specify 1000, the addresses you access are out of the segment.

std::make_unique<int>(Size);
This doesn't do what you are expecting!
It creates single int and initializes it into value Size!
I'm pretty sure your plan was to do:
auto p = std::make_unique<int[]>(Size)
Note extra brackets. Also not that result type is different. It is not std::unique_ptr<int>, but std::unique_ptr<int[]> and for this type operator[] is provided!
Fixed version, but IMO you should use std::vector.

Related

Why does my code occasionally show memory on the free store (heap) growing both up and down? (C++)

My understanding is that memory allocated on the free store (the heap) should grow upwards as I allocate additional free store memory; however, when I run my code, occasionally the memory location of the next object allocated on the free store will be a lower value. Is there an error with my code, or could someone please explain how this could occur? Thank you!
int main()
{
int* a = new int(1);
int* b = new int(1);
int* c = new int(1);
int* d = new int(1);
cout << "Free Store Order: " << int(a) << " " << int(b) << " " << int(c) << " " << int(d) << '\n';
// An order I found: 13011104, 12998464, 12998512, 12994240
delete a;
delete b;
delete c;
delete d;
return 0;
}
The main problem with that code is that you are casting int * to int, an operation that may lose precision, and therefore give you incorrect results.
But, aside from that, this statement is a misapprehansion:
My understanding is that memory allocated on the free store (the heap) should grow upwards as I allocate additional free store memory.
There is no guarantee that new will return objects with sequential addresses, even if they're the same size and there have been no previous allocations. A simple allocator may well do that but it is totally free to allocate objects in any manner it wants.
For example, it may allocate in a round robin method from multiple arenas to reduce resource contention. I believe the jemalloc implementation does this (see here), albeit on an per-thread basis.
Or maybe it has three fixed-address 128-byte buffers to hand out for small allocations so that it doesn't have to fiddle about with memory arenas in programs with small and short-lived buffers. That means the first three will be specific addresses outside the arena, while the fourth is "properly" allocated from the arena.
Yes, I know that may seem a contrived situation but I've actually done something similar in an embedded system where, for the vast majority of allocations, there were less than 64 128-byte allocations in flight at any given time.
Using that method means that most allocations were blindingly fast, using a count and bitmap to figure out free space in the fixed buffers, while still being able to handle larger needs (> 128 bytes) and overflows (> 64 allocations).
And deallocations simply detected if you were freeing one of the fixed blocks and marked it free, rather than having to return it to the arena and possibly coalesce it with adjacent free memory sections.
In other words, something like (with suitable locking to prevent contention, of course):
def free(address):
if address is one of the fixed buffers:
set free bit for that buffer to true
return
call realFree(address)
def alloc(size):
if size is greater than 128 or fixed buffer free count is zero:
return realAlloc(size)
find first free fixed buffer
decrement fixed buffer free count
set free bit for that buffer to false
return address of that buffer
The bottom line is that the values returned by new have certain guarantees but ordering is not one of them.

dynamic memory allocation using new with binary search in C++

I am trying to find the maximum memory allocated using new[]. I have used binary search to make allocation a bit faster, in order to find the final memory that can be allocated
bool allocated = false;
int* ptr= nullptr;
int low = 0,high = std::numeric_limits<int>;
while(true)
{
try
{
mid = (low + high) / 2;
ptr = new int[mid];
delete[] ptr;
allocated = true;
}
catch(Exception e)
{....}
if (allocated == true)
{
low = mid;
}else
{
high = low;
cout << "maximum memory allocated at: " << ptr << endl;
}
}
I have modified my code, I am using a new logic to solve this. My problem right now is it is going to a never ending loop. Is there any better way to do this?
This code is useless for a couple of reasons.
Depending on your OS, the memory may or may not be allocated until it is actually accessed. That is, new happily returns a new memory address, but it doesn't make the memory available just yet. It is actually allocated later when and if a corresponding address is accessed. Google up "lazy allocation". If the out-of-memory condition is detected at use time rather than at allocation time, allocation itself may never throw an exception.
If you have a machine with more than 2 gigabytes available, and your int is 32 bits, alloc will eventually overflow and become negative before the memory is exhausted. Then you may get a bad_alloc. Use size_t for all things that are sizes.
Assuming you are doing ++alloc and not ++allocation, it shouldn't matter what address it uses. if you want it to use a different address every time then don't delete the pointer.
This is a particularly bad test.
For the first part you have undefined behaviour. That's because you should only ever delete[] the pointer returned to you by new[]. You need to delete[] pvalue, not value.
The second thing is that your approach will be defragmenting your memory as you're continuously allocating and deallocating contiguous memory blocks. I imagine that your program will understate the maximum block size due to this fragmentation effect. One solution to this would be to launch instances of your program as a new process from the command line, setting the allocation block size as a parameter. Use a divide and conquer bisection approach to attain the maximum size (with some reliability) in log(n) trials.

the amount of dynamic allocated memory a pointer would take in c++

I have a program:
#include <iostream>
using namespace std;
int main(){
const int SIZE = 1000;
typedef int* IntPointer;
IntPointer ip;
do {
ip = new int[ SIZE ];
cout << "Memory allocated " << endl << flush;
} while (ip != nullptr);
}
This code is suppose to test the amount of memory used by the ip every time it loops.
I tried to print out the value of ip, which is the memory address in hex I believe, I can see everytime it loops once, the address will increase 4000 in dec. So, is it correct that every ip will take 4000 bytes memory? I am wondering if there is any function to get the value of memory used by every ip? If not, how do I get the size of cumulative memory use within the loop?
Appreciate your answer. Thank you!
I don't know why you have to allocate memory to know about this.
To get size of one pointer use below,
cout << "Memory allocated for one IntPointer :"<<sizeof(IntPointer);
To get size of 1000 Int* objects use as below,
cout << "Memory allocated for "<< SIZE <<" IntPointers :"<<sizeof(IntPointer*SIZE );
you are getting 4000 as you allocate memory for 1000 int* i.e 4*1000 = 4000.
A integer is on your system 4 bytes. So having a int array of 1000 -> 4000 bytes. That's correct. The std::cout << sizeof(int) << std::endl; function will show you that your integer has a size of 4 bytes.
There is no portable way to get the ammount of memory allocated at runtime. You can get the amount of memory by tracking the size and using sizeof(int)*SIZE byte for the array. You can't get the memory at runtime using sizeof. sizeof is a compile time operator.
The memory allocator will also allocate a struct internally to track the memory chunk and the size of it, but this bookkeeping struct isn't usually your concern, unless you want to make your own memory allocator.
You can use the sizeof() function to get the size in bytes. Make sure to dereference the pointer however, otherwise you'll get the size of the pointer itself, not the memory it points to. Plus just a note, make sure you get around to releasing memory allocated by a pointer. Anything you put on the heap is your own problem, unlike the stack. (You may already be aware but it doesn't hurt to reiterate.)
In your code, most of the data is simply lost, as your pointer can only point at one thing at a time.
Edit: Reading this correctly now, yeah you can't just get the size of the array. Dereferencing will just give you the size of the first element. You know the count of the array however, so you can simply multiply. If your elements could be different sizes (which in your case they can't) I'm not entirely sure of what you would do.

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

C++ - The start of block memory

I mean to give pointer to variable in struct\memory and then give it to some function and it'll give me pointer to the start of the struct\memory.
There is a function that does it?
To understand this question:
char* ptr=((char*)malloc(12))+3;
//MemStart(ptr) == ptr-3
MemStart'll be the function that'll give that result in the code.
Unless there is something specific to that structure's representation in memory (such as it always starts with the bytes 0xff, 0xff), there is no way to determine where a particular structure or array starts. Modern architectures are Von Neuman machines, meaning memory has no inherent meaning.
Note that many architectures have alignment issues or optimizations, meaning structures or arrays may need to start on 16-bit, 32-bit or 64-bit word boundaries, but these are architecture specific.
[Edit: Added the following]
The library may introduce guard bytes at the start or end of the allocated block of memory or fill memory with known constants to look for buffer overflows or errant pointers. However, these are usually omitted in release mode and, even if they are present, may also be valid data.
You could inspect the memory allocation table for dynamically allocated memory but the array/struct could be allocated on the stack rather than the heap. Also, what happens if you have a structure within an array? Which value does it return? If you want to restrict it to just dynamically allocated memory where you want the start of whatever memory was allocated only, Basile has a great answer.
Most malloc implementations don't provide what you want (the starting address of a dynamically allocated block, given some internal pointer to it). And the standards don't require anything like that. So you may want to use both pointer to base, and offset (perhaps packing them inside some C++ class fat_pointer with operator* and operator-> giving the illusion of pointers, etc, etc).
You could of course re-implement your own malloc above operating system memory segment allocation (i.e. mmap(2) on Linux or Posix) and de-allocation munmap(2) primitive syscalls.
You could also have your specialized allocator; it might allocate your zones with a large power-of-two alignment (e.g. 256 or 4096 bytes) using posix_memalign, then use bits manipulation on the intptr_t cast of your pointer.
Notice that implementing any serious memory allocator means caring about unportable details of your operating system and architecture (alignment, ...).
You could also use Boehm's conservative garbage collector, that is use GC_malloc instead of malloc (and don't bother GC_free-ing your dynamic data); then you have the GC_base function which does exactly what you want:
/* Return a pointer to the base (lowest address) of an object given */
/* a pointer to a location within the object. */
/* I.e. map an interior pointer to the corresponding bas pointer. */
/* Note that with debugging allocation, this returns a pointer to the */
/* actual base of the object, i.e. the debug information, not to */
/* the base of the user object. */
/* Return 0 if displaced_pointer doesn't point to within a valid */
/* object. */
/* Note that a deallocated object in the garbage collected heap */
/* may be considered valid, even if it has been deallocated with */
/* GC_free. */
GC_API void * GC_base(void * displaced_pointer);
You can use the offsetof() macro from <cstddef>:
#include <cstddef>
#include <iostream>
using namespace std;
typedef struct
{
int a;
int b;
} S;
int main()
{
S s = { 1, 2 };
cout << "address of s:" << &s << endl;
cout << "address of s.a:" << &s.a << endl;
cout << "address of s.b:" << &s.b << endl;
int* pb = &s.b;
S* ps = (S*)((char*)pb - offsetof(S, b));
cout << "ps:" << ps << endl;
return 0;
}
Output (ideone):
address of s:0xbffd266c
address of s.a:0xbffd266c
address of s.b:0xbffd2670
ps:0xbffd266c