Because segmentation fault related to malloc/free happens, I would like to convert malloc/free to new/delete.
Error occurred when malloc/free is converted to below.
Let me know how to solve it.
(original)
char *only_valid_data = static_cast<char*> (malloc (data_size));
(converted)
char *only_valid_data = new static_cast<char*> [data_size];
Just do
char* only_valid_data = new char[data_size];
to allocate.
To free you do
delete[] only_valid_data;
Important note: When you allocate memory with new it will allocate data_size elements, not data_size bytes (like malloc does). The size of an element is the size of the non-pointer base type, in your case e.g. sizeof(*only_valid_data). In this case the element size and the byte size is the same (as sizeof(char) is specified to always be 1), but if the base type is something else it will make a big difference.
For example, if you do
int* int_ptr = new int[10];
then ten integers will be allocated, not ten bytes. This is equivalent to
int* int_ptr = reinterpret_cast<int*>(malloc(10 * sizeof(*int_ptr)));
Also note that for complex types, like structures and classes, allocating with new (or new[]) does more than just allocating memory, it will also make sure that the allocated object(s) constructor is called. The malloc function only allocates memory, it doesn't call the constructor.
Final note: The problem you have with the segmentation fault is probably not caused by your allocation, no matter how you allocate the memory. The problem is more likely because of something else, something you do not show in your question, like writing out of bounds of the allocated memory or dereferencing a null-pointer.
You need run your program in a debugger to catch the crash in action, it will allow you to examine the function call stack, and if the crash doesn't happen in your code then you walk up the call stack until you reach your code. There you can examine the values of variables, to help you understand why the problem occurred.
The malloc family (malloc, realloc, calloc, free) is used almost always in C code, as C++ provides the new and delete operators which are a lot more reliable to use.
A problem with malloc for allocation is that you must specify the size of the type in bytes that you want to allocate. For example:
int* ptr = malloc(5);
Will not allocate space for 5 integers in memory; it will allocate 5 bytes of memory (the size of an integer is 4 bytes, so this would obviously cause problems when assigning).
To do it properly, it must be written as
int* ptr = malloc(5 * sizeof(int));
So that 20 bytes are allocated.
However, there are some exceptions to the case. char, for example only requires one byte of memory, so doing
char* ptr = malloc(5);
Will allocate enough memory to hold 5 characters, and in a way is more valid that writing:
char* ptr = malloc(5 * sizeof(char)); //5 * sizeof(char) == 5 * 1 == 5
However, the free function does not need to know the size of the pointer to be deallocated; a void* is only needed.
Note that in C++, the return of malloc must be cast properly to the type wanted; malloc returns a void* type, but C++ does not allow any pointer to assign a void* to any pointer type like C does:
int* ptr = malloc(5 * sizeof(int)); //valid C code, invalid C++
int* ptr2 = (int*)malloc(5 * sizeof(int)); //valid C code, valid C++
In C++, the new[] operator resolves the issue of remembering to add the sizeof operator.
int* ptr = new int[5];//allocates 5 integers
int* ptr2 = new int(5);//be careful: this allocates a single integer with value of 5
Note that if the new[] operator has been used, the delete[] operator must be used. Otherwise the delete operator must be used:
int* ptr = new int[5];//allocates 5 integers
delete[] ptr;//deallocate the 5 integers
int* ptr2 = new int(5);//be careful: this allocates a single integer with value of 5
delete ptr;//deallocate the integer
The problem with your code is that it does not fit the syntax of the new[] operator
The syntax could be described as:
T* p = new T[size];
Thus your code:
char *only_valid_data = new static_cast<char*> [data_size];
Should be corrected to:
char *only_valid_data = new char[data_size];
As static_cast<char*> is not a type.
Hope this helps :)
Related
I'm trying to free the memory of the allocated array inside struct _Stack, but the program keeps crashing
typedef struct _Stack
{
int top;
unsigned int capacity;
int* arr;
}_Stack;
_Stack* createStack(int capacity)
{
_Stack* stack = (_Stack*) malloc(sizeof(_Stack));
stack->capacity = capacity;
stack->top = -1;
stack->arr = (int*) malloc(sizeof(stack->capacity * sizeof(int)));
return stack;
}
I'm using this function to free the memory, but the program crashes here.
// I have a problem here.
void stack_free(_Stack* stack)
{
free(stack->arr);
free(stack);
}
Change this:
stack->arr = (int*) malloc(sizeof(stack->capacity * sizeof(int)));
to this:
stack->arr = (int*) malloc(stack->capacity * sizeof(int));
since you want the size of the array to be equal to stack->capacity * sizeof(int), and not equal to the size of that expression.
Your program must have invoked Undefined Behavior somewhere in code not shown in the question (because of the wrong size malloc'ed), that's why it crashes later.
PS: Since you use C++, consider using new instead (and delete, instead of free()).
sizeof(stack->capacity * sizeof(int)) in your call to malloc is wrong. Instead of the size of the array, it gives the size of the number used to represent the size of the array. You probably want stack->capacity * sizeof(int).
Another possible problem is that in C you should not cast the return value of malloc, since it can hide other mistakes and cause a crash. See Do I cast the result of malloc?
In C++ you will have to do it, because of the stricter type checking in C++, but it can still hide problems.
These are the problems I see with the code you have shown. However, remember that errors in malloc and free are not necessarily caused by the actual line where they are detected. If some part of your program damages the malloc system's internal data structures, for example by a buffer overrun, the problem can manifest in a much later call to malloc or free, in a completely different part of the program.
I have a C++ code...
// global
DWORD* P;
DWORD (*S)[256];
// then later allocate memory
P = new DWORD[18];
S = new DWORD[4][256];
// later on, free memory
delete P;
delete [] S;
that I want to convert to C. I tried ..
/* global */
DWORD* P;
DWORD (*S)[256];
/* allocate */
P = malloc(sizeof(DWORD[18]));
S = malloc(sizeof(DWORD[4][256]));
/* free */
free(P);
free(S);
It works and I don't get any errors or warnings from the compiler (GCC) but I'm not sure if this is the right way, and I'm guessing it leaks memory, probably in freeing the multidimensional array.
Also, are those arrays too big to allocate on the stack? Can I do it like this instead and forget about malloc/free?
DWORD P[18] = {0};
DWORD S[4][256] = {{0}};
That code is perfectly safe. malloc() and free() are only concerned with allocating a number of bytes from the heap. This is why you use sizeof() inside the call to malloc(), to determine the number of bytes that datatype needs. You could also, for example, do S = malloc(sizeof(DWORD) * 4 * 256) and get the same result.
To answer the second half of your question, neither of those arrays are even close to being too big for the stack. You could stack-allocate those in either C or C++.
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.
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.
Bit confused about usage of new to allocate memory dynamically.
e.g. If I need to allocate memory for 100 ints(assuming int is 4 bytes), should I say :
int *ptr = new int[100];
or
int *ptr = new int[100*4]; //assuming int is 4 bytes.
Basially new operator allocates memory in bytes or that many bytes of type T used while invoking the new operator?
If my class doesn't have a allocator member function defined, & i need to allocate an array of object of that class type, will the new oeprator find the sizeof(class type) and allocate accordingly or how would it work?
EDIT:
Sorry for clubbing multiple questions, but its related:
will this piece of code work fine if i want to allocate a 2D array of size [100][4] of ints
int *arr = new int [100][4];
thank you.
-AD
The size given to new is the number of items, not the memory size. However, consider using std::vector instead.
For example, new int[100] allocates at least 100 * sizeof(int) bytes (which is 400 when sizeof(int) is 4); any more it allocates will be due to implementation and runtime details which you (except for very rarely) cannot depend on.
If you don't have an operator new or operator new[] in your class (which you usually shouldn't), then the global versions will be used, and they will use sizeof(your_type) correctly.
Did you try the code in the update?
Multidimensional arrays are actually arrays of arrays; so new returns a pointer to the first item just as it does for single dimensional arrays, which is a pointer to an array:
typedef int int4[4]; // for clarity
int4 *arr = new int4[100];
// above two lines are identical to:
int (*arr)[4] = new int[100][4];
Again, you're almost always better off using a container than managing this yourself. That's vector, et. al., but also containers like boost::array and dedicated "matrix" types for "square" 2-dimensional arrays.
The confusion may come because of malloc which uses data size, not the number of items. To allocate an array of 100 integers, you can do:
int *ptr = (int *)malloc(100 * 4);
or (better, works for all platforms because an int is not always 4 bytes long):
int *ptr = (int *)malloc(100 * sizeof(int));
instead of:
int *ptr = new int[100];
which, as Fred says, automatically uses the data size to allocate the correct area. Of course malloc can only be used for built-in types such as int.