Unexpected size when using malloc() - c++

I wanted to test my knowledge, and wrote a small program, which looks like this:
#include <iostream>
#include <cstdlib>
int main()
{
int* mem1 = (int*) malloc(2 * sizeof(int));
int* mem2 = (int*) malloc(5 * sizeof(int));
std::cout << "mem1: " << sizeof(mem1) << std::endl;
std::cout << "mem2: " << sizeof(mem2) << std::endl;
return 0;
}
I get the output:
mem1: 8
mem2: 8
When I change the values, that malloc(2 * sizeof(int)) to malloc(3 * sizeof(int)), the output also doesn't change.
This is the Tutorial I used, so I am not entirely sure, if this is memory safe, with the conversion to int* when calling malloc.
I have also found this question, but I don't find it to be very helpful in my case.
Clang++ is the Compiler I used, but I don't think it makes any difference.
My best guess is, that it allocates the same memory, because it doesn't know where the memory ends.

sizeof is telling you the compile-time size of the pointer (it would report the same value even if you never called malloc at all). There is no standards-compliant way to determine the amount of memory allocated by malloc; you have to store it side-band if you need to preserve that information.

The 8 bytes that you see is the size of the pointer(int*). sizeof() is done at compile time and there's no way for the compiler to know this size at compile time(malloc is dynamic memory allocation).

The expression sizeof(mem1) will always return the same value, no matter the size of the allocated memory block! This is because mem1 is a pointer to the allocated memory, and the size of a pointer does not change (within a given environment, that is).
In your case (presumably, a build on a 64-bit platform) pointers are 8 bytes in length. You could build this for a different platform (say, a 32-bit system) and you may get a different size (for example, 4); but, on that platform, that size will then always be 4.

As mentioned above, there are a few problems in this question:
In C++ you dynamically allocate memory using the new operator. The option of using malloc is for working with c-style APIs, when needed dynamic allocations that will be de-allocated by c-free function. In order to make such an allocation, it is best advised to use std::malloc which you can read about in this link (cpp reference).
The operator sizeof is calculating the size of the static type, meaning that it is giving you back the size of integer pointer, which is constant, depending on your CPU architecture.
Working with raw pointers in C++ is ill-advised, you should always make sure that for each item dynamically created in memory there is an owner, that is the one responsible to delete it when no longer needed. In C++11 and later, this can be achieved by using smart pointers, such as std::unique_ptr. In fact, C++ has created a great Idiom for resource management, called RAII (Resource Allocation Is Initialization), which sets it apart from many other languages.

Related

C++ programming, dynamical memory is not working properly using malloc and calloc

I have just started learning C++ and I came on a problem I couldn't find on the Internet so I hope you can help me with.
This is my code:
int* a;
int* b;
a = (int*)calloc(1, sizeof(int));
b = (int*)calloc(5, sizeof(int));
cout << sizeof(a) << endl;
cout << sizeof(b) << endl;
What compiler returns me is: 8, 8.
If I use:
cout << sizeof(*a) << endl;
cout << sizeof(*b) << endl;
Compiler returns 4, 4.
The same thing is with malloc. I am using .
What am I doing wrong? Why isn't the size of b 20 as it is 5 times bigger if int is 4 bytes long?
Thanks!
sizeof(*a) and sizeof(*b) are always going to be equal to 4. It seems you expect them to return the size of arrays, but you need to understand that a and b are not arrays. They are pointers to int. If sizeof(int) is 4, then sizeof(*a) is also going to be 4, and this is already known at compile time.
With that being said, you do not need to use the C library functions malloc() and calloc() in C++. If you need manual memory allocation, use new and delete:
a = new int;
b = new int[5];
If you need to do zero-initialization like calloc does, just use () to default-construct the allocated integers:
a = new int();
b = new int[5]();
Instead of free(), use delete or delete[], depending on how new was called previously:
delete a; // Note: no '[]'
delete[] b; // Needs '[]'
However, you do not need manual memory allocation here. Just use std::vector<int>:
#include <vector>
// ...
std::vector<int> a(5); // 5 int elements, zero-initialized.
std::cout << a.size() << '\n'; // Will print '5'.
As a rule of thumb, your C++ code should not have any calls to new, delete, malloc(), calloc() or free(). Doing manual memory management requires more code and is error-prone. Use containers like vector and smart pointers like shared_ptr and unique_ptr instead to reduce the chance of memory and other resource leaks. These safer types are also more convenient. With vector for example, you do not have to remember the size of your allocated memory yourself. The vector keeps track of its size for you. You can also copy vectors easily by just assigning them directly. You also don't need to delete or free() vectors manually. They are automatically deleted when they go out of scope.
As a side-note, I recommend getting rid of the habit of using endl for printing newlines. endl flushes the stream, it doesn't just print a newline. If you use it, you will be constantly flushing the output stream, which is a slow operation. You only rarely need to flush a stream, in which case you can just do so manually with << flush if the need ever arises.
You are taking the sizeof a pointer in the first case and the size of the element int the second. *a is for your intents and purposes the same as a[0]. The size of the pointer is architecture dependent, and the size of the int is 4.
The sizeof value is evaluated at compile time. Dynamic memory allocation occurs at runtime. To find out the amount allocated at run time you can look at overloading the new operator (not recommended) or using the containers as the comments have suggested.
sizeof(a) is the size of the pointer (this is 8 in a 64bit architecture normally), while sizeof(*a) is the size of the pointed to element (an integer value). Nothing returned by sizeof operator has dynamic nature (as the number of elements returned by calloc(3))
By the way, calloc() is strongly deprecated in C++. Its use is reserved to cases in which you have to pass the pointers to C code and for legacy code. Use the operators new and new [] (the last one in this case). But none of these will change things, the sizeof operator will continue returning the values you got. If you want to check the size of the returned array, then check the parameters passed to both operators.

How would I use the sized operators delete/delete[] and why are they better?

C++14 introduced "sized" versions of operator delete, i.e.
void operator delete( void* ptr, std::size_t sz );
and
void operator delete[]( void* ptr, std::size_t sz );
Reading through N3536, it seems that those operators were introduced to increase performance. I know that the typical allocator used by operator new "stores" the size of the bulk memory somewhere, and that's how typical operator delete "knows" how much memory to return to the free store.
I am not sure however why the "sized" versions of operator delete will help in terms of performance. The only thing that can speed things up is one less read operation regarding the size from the control block. Is this indeed the only advantage?
Second, how can I deal with the array version? AFAIK, the size of the allocated array is not simply sizeof(type)*number_elements, but there may be some additional bytes allocated as the implementation may use those bytes as control bytes. What "size" should I pass to operator delete[] in this case? Can you provide a brief example of usage?
Dealing with your second question first:
If present, the std::size_t size argument must equal the size argument passed to the allocation function that returned ptr.
So, any extra space that might be allocated is the responsibility of the runtime library, not the client code.
The first question is more difficult to answer well. The primary idea is (or at least seems to be) that the size of a block often isn't stored right next to the block itself. In most cases, the size of the block is written, and never written again until the block is deallocated. To avoid that data polluting the cache while the block is in use, it can be kept separately. Then when you go to deallocate the block, the size will frequently have been paged out to disk, so reading it back in is quite slow.
It's also fairly common to avoid explicitly storing the size of every block explicitly at all. An allocator will frequently have separate pools for different sizes of blocks (e.g., powers of 2 from 16 or so up to around a couple kilobytes or so). It'll allocate a (fairly) large block from the OS for each pool, then allocate pieces of that large block to the user. When you pass back an address, it basically searches for that address through the different sizes of pools to find which pool it came from. If you have a lot of pools and a lot of blocks in each pool, that can be relatively slow.
The idea here is to avoid both of those possibilities. In a typical case, your allocations/deallocations are more or less tied to the stack anyway, and when they are the size you're allocating will likely be in a local variable. When you deallocate, you'll typically be at (or at least close to) the same level of the stack as where you did the allocation, so that same local variable will be easily available, and probably won't be paged out to disk (or anything like that) because other variables stored nearby are in use as well. For the non-array form, the call to ::operator new will typically stem from a new expression, and the call to ::operator delete from the matching delete expression. In this case, the code generated to construct/destroy the object "knows" the size it's going to request (and destroy) based solely on the type of object being created/destroyed.
For the size argument to C++14 operator delete you must pass the same size you gave to operator new, which is in bytes. But as you discovered it's more complicated for arrays. For why it's more complicated, see here: Array placement-new requires unspecified overhead in the buffer?
So if you do this:
std::string* arr = new std::string[100]
It may not be valid to do this:
operator delete[](arr, 100 * sizeof(std::string)); # BAD CODE?
Because the original new expression was not equivalent to:
std::string* arr = new (new char[100 * sizeof(std::string)]) std::string[100];
As for why the sized delete API is better, it seems that today it is actually not but the hope is that some standard libraries will improve performance of deallocation because they actually do not store the allocation size next to each allocated block (the classical/textbook model). For more on that, see here: Sized Deallocation Feature In Memory Management in C++1y
And of course the reason not to store the size next to every allocation is that it is a waste of space if you don't truly need it. For programs which make many small dynamic allocations (which are more popular than they ought to be!), this overhead can be significant. For example in the "plain vanilla" std::shared_ptr constructor (rather than make_shared), a reference count is dynamically allocated, so if your allocator stores the size next to it, it might naively require about 25% overhead: one "size" integer for the allocator plus the four-slot control block. Not to mention memory-pressure: if the size is not stored next to the allocated block, you avoid loading a line from memory on deallocation--the only information you need is given in the function call (well, you also need to look at the arena or free-list or whatever, but you needed that in any case, you still get to skip one load).
Some relevant info: Currently VS 17 implementation of sized delete[] seems broken. It always returns the generic pointer size (void*). The g++ 7.3.1 give the size of the full array plus 8 bytes overhead. Haven't tested it on other compilers, but as you see neither of them giving the expected result.
WRT to usefulness of it, as is alluded to in the selected answer, the main usefulness come in play when you have your custom allocators, either to pass to stl containers or just use for local memory management. In these cases it could be very useful to have user size array size be returned to you, so you can free the proper size from your allocators. I can see it is possible to avoid having to use this though. Here's a code you can use for testing the "correctness" of sized delete[] implementation in your compiler:
#include <iostream>
#include <sstream>
#include <string>
std::string true_cxx =
#ifdef __clang__
"clang++";
#elif _MSC_VER
"MVC";
#else
"g++";
#endif
std::string ver_string(int a, int b, int c) {
std::ostringstream ss;
ss << a << '.' << b << '.' << c;
return ss.str();
}
std::string true_cxx_ver =
#ifdef __clang__
ver_string(__clang_major__, __clang_minor__, __clang_patchlevel__);
#elif _MSC_VER
#ifdef _MSC_FULL_VER
#if _MSC_FULL_VER == 170060315
"MSVS 2012; Platform Toolset v110";
#elif _MSC_FULL_VER == 170051025
"MSVS 2012; Platform Toolset v120_CTP_Nov2012";
#elif _MSC_FULL_VER == 180020617
"MSVS 2013; Platform Toolset v120";
#elif _MSC_FULL_VER == 191426431
"MSVS 2017; Platform Toolset v140";
#else
"Not recognized";
#endif
#endif // _MSC_FULL_VER
#else
ver_string(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#endif
// sized class-specific deallocation functions
struct X {
static void operator delete(void* ptr, std::size_t sz)
{
std::cout << "custom delete for size " << sz << '\n';
::operator delete(ptr);
}
static void operator delete[](void* ptr, std::size_t sz)
{
std::cout << "custom delete[] for size " << sz << '\n';
::operator delete(ptr);
}
char16_t c[2];
};
int main() {
X* p1 = new X;
delete p1;
X* p2 = new X[10];
for (int i = 0; i < 10; ++i)
p2[i] = X{ (char16_t)i };
std::cout << "Compiler: "<<true_cxx.c_str()<<": Version:" << true_cxx_ver.c_str() << std::endl;
delete[] p2;
}

C Program works for me but shows runtime error online

The following code worked fine for me (code blocks 10.05) and showed no compile-time/runtime errors for various test cases.
But showed runtime error as I submitted it online on a programming website.
#include<stdio.h>
#include<stdlib.h>
/*
Here comes newPos()
*/
int main()
{
int t,i,n,k,j;
scanf("%d",&t);
int* a;
for(i=0;i<t;i++)
{
scanf("%d",&n);
free(a);
a=(int*) malloc(n);
for(j=0;j<n;j++)
scanf("%d",&a[j]);
scanf("%d",&k);
printf("%d\n",newPos(a,n,k));
}
return 0;
}
And then I changed it into a .cpp file after making a few changes.
i.e., instead of free(a) I used the statement, delete a; and instead of a=(int*) malloc(n), I used the statement, a=new int[n];
Then it executed successfully both on my compiler and online.
First error:
You are not allocating enough memory to store n integer values. So you should change:
a=(int*) malloc(n);
to:
a=malloc(n * sizeof(int));
I have also removed the cast since it's useless and could hide a forgotten include.
Second error:
You must not free a before allocating memory. Free the memory only at the end of your loop.
C/C++ mix:
In the comments of this answer, people are talking about the need or not to cast, in particular in C++. In C, you should not cast.
If you are willing to do C++ code, you should use new and delete instead of malloc and free. Honestly, I don't know if a cast is needed in C++ when using malloc, because in C++, I always use new. But please, don't write C code with a C++ compiler. Choose between C and C++ depending on your needs.
You are freeing before allocating:
free(a); // This can lead to Undefined Behavior because a is containing some junk value
a=(int*) malloc(n);
Also, no specific need to cast return type of malloc and check your malloc argument you are not specifying size in bytes correctly. But in C++ the case is required (Since you tagged both C and C++).
Do I cast the result of malloc?
a=(int*) malloc(n*sizeof(int));
Aside from the mentioned allocation size problem, you can't free(a) unless you have either already allocated something, or have initialized a to have the value NULL.
This is because your argument to malloc() is wrong. The function has no idea what "unit" you're going to be using, so the unit for the argument is always "bytes". With C++'s new[] operator, that's operating a higher level in the language so it can take the type's size into account.
Thus, change your allocation to:
a = malloc(n * sizeof *a);
This removes the pointless and annoying cast, and also adds the missing sizeof to scale the argument by the number of bytes in each pointed-to object. This is a good form of malloc() usage to remember.
Also don't free() random pointers.

Memory allocation for incremental garbage collection simulation in c++

I need to simulate an incremental garbage collection algorithm in C++ or Java. I had a doubt based on this.
As an input (stdin from keyboard), I will be asked to allocate some memory for this code. The syntax would be:
x = alloc(128KB);
My question: is it ok to use malloc for the assignment? Or is there any other way to allocate memory? I had this doubt because, the size can go up to GB for the assignment, so using malloc might not be a good idea I think.
First of all, if you want to prohibit a huge memory allocation, just check users' input value, but I'm not sure how much memory you think as a huge memory. I think you don't worry about that, because if memory allocation failed, malloc and calloc will return a NULL pointer.
Secondly, you can also use 'calloc' for this case.
void calloc(size_t num, size_t size);
'num' is mean elements' count for allocation and 'size' is, of course, the size of element. Below codes have the same result.
ar = (int *)malloc(5 * sizeof(int));
ar = (int *)calloc(5, sizeof(int));
However, if you choose 'calloc', you may manage more logically your code, since you can divide memory quantity by unit and count.
Also, if you use 'calloc', you don't need to use memset for setting memory value to zero.
'calloc' set automatically memory value to zero.
I hope this article can help you.
malloc can allocate as much memory as you wish provided you don't go past ulimits. Give the following a go to test it out:
#include <stdlib.h>
#include <string.h>
#define ONEGB (size_t)(1073741824)
int main() {
char *p;
p = malloc(ONEGB);
if (!p) {
perror("malloc");
}
else {
memset(p, 0, ONEGB);
}
return 0;
}

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