The correct way to convert malloc to new - c++

I am changing c code to c++ code and this is how how i have converted malloc to new
frame.p_data = (uint8_t*)malloc(xres * yres * 4);
free(frame.p_data);
frame.p_data = (uint8_t*)operator new(xres * yres * 4);
delete(frame.p_data);
Is this the correct way to change from malloc to new and would the delete release all the data.

No, you should write
frame.pdata = new uint8_t[xres * yres * 4];
delete [] frame.pdata;
It is very rare to call the allocation function operator new explicitly, but if you do, you need to match it with the deallocation function, operator delete, otherwise the behaviour is undefined:
frame.p_data = (uint8_t*)operator new(xres * yres * 4);
operator delete(frame.p_data);
It's also not a problem to use malloc with primitive types, as long as you remember to deallocate with free, but it's easier to stick to new/delete and not have to remember.

This answer shows how to use new/delete, but this recommendation just does not seem right/complete.
The correct way (that will pass a mainstream code-review), is not replace it with new/delete in the first place, but go directly to containers/smart pointers. std::vector (or std::array if static size) has all the tools needed, since std::vector is the dynamic array in c++. If the size tracking overhead is too much, then std::unique_ptr or std::array.
simplified example:
std::vector<uint8_t> data;
data.resize(xres * yres * 4);
uint8_t* pdata = data.data(); // <- access to raw buffer
A few guidelines regarding this:
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-newdelete
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ri-raw

Related

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.

dynamic allocation (arrays) with string or char

there is no problem here:
int *x;
x = (int *) malloc(0 * sizeof(int));
int value = 5;
x = (int *) realloc(x,(value)*sizeof(int));
But I cant do that for strings :\
I wanna do that for a y[] array, like this:
y[0]="hello"
y[1]="how are you"
how can I do that?
std::vector<std::string> y;
y.push_back("hello");
y.push_back("how are you");
Don't use malloc, or realloc, or free in C++. Don't use char* for purposes other than interop. Stay away from pointers until you actually need them (same for arrays).
You cannot use realloc on an array of std::string objects because realloc moves things around by bit copying and this is not allowed on general objects.
The standard class std::vector is a generic container for objects that moves and copies things around correctly (using copy constructors, assignments and similar methods) and that can change its size for example with the resize method. All the needed memory is allocated and freed automatically as needed.
With std::vector for example you can write code like...
std::vector<std::string> v; // An empty vector
v.resize(10); // Now size is 10 elements (all empty strings "")
v[0] = "Hello"; // First element is now the string "Hello"
v[1] = "world."; // Second element is now the string "world."
v.resize(2); // Now v.size() is 2
v.push_back("How's going"); // Now the size is 3 and third element is filled.
Do yourself a favor and pick up a good C++ book, reading it cover to cover. C++ is a powerful but complex language and if you try to learn it by experimenting with a compiler you're making a terrible mistake for many reasons.
What you're doing right now is not C++ ... you can do what you want with C-style strings, but you would need an array of pointers to type char that allow you to access the allocated memory for each string in the array. This can be done like so:
char* y[2];
y[0] = strdup("hello");
y[1] = strdup("how are you");
You also need to keep in mind that your y array now "owns" the pointers, so you must call free() on each pointer in the array in order to avoid any memory leaks should you decide to change the strings each pointer is pointing to.
If you want to go with an idiomatic C++ solution though, and not revert to C-style strings, then you should be using std::string and std::vector ... doing so avoids the issues with memory leaks as well as allocating and deallocating the memory associated with dynamically allocated C-strings.
You can actually do exactly what you need exactly like with integers:
typedef const char *c_string;
c_string *y;
y = (c_string *) malloc(0 * sizeof(c_string));
int value = 5;
y = (c_string *) realloc(y,(value)*sizeof(c_string));
y[0]="hello";
y[1]="how are you";
This won't work with non-const char * though, so this example is of limited usability.

How do I delete this Void Pointer?

#define ALIGNBUF(Length) Length % ALIGNSIZE ? \
Length + ALIGNSIZE - (Length % ALIGNSIZE) : Length
short NumCols;
long * ColLenArray, * OffsetArray;
ColLenArray = new long(NumCols * sizeof(long));
OffsetArray = new long(NumCols * sizeof(long));
// THIS CODE SHOULD NOT BE NEEDED TO UNDERSTAND THE PROBLEM
// BUT I HAVE INCLUDED IT JUST IN CASE
////////////////////////////////////////////////////////////
SQLColAttribute(hstmt, ((SQLUSMALLINT) i)+1, SQL_DESC_OCTET_LENGTH, NULL, 0, NULL, &ColLenArray[i]);
ColLenArray[i] = ALIGNBUF(ColLenArray[i]);
if (i)
OffsetArray[i] = OffsetArray[i-1]+ColLenArray[i-1]+ALIGNBUF(sizeof(SQLINTEGER));
////////////////////////////////////////////////////////////
void **DataPtr = new void*[OffsetArray[NumCols - 1] + ColLenArray[NumCols - 1] + ALIGNBUF(sizeof(long))];
delete []DataPtr;
Don't think it can be done, have tried every way imaginable.
This code works, as in the program runs, I just can't deallocate the memory. Every time this code is called(not all code included as it isn't relevant) the memory gets bigger. I think that deletion is not happening properly and that the void * keeps growing.
I have also changed some of the code above based on recommendations here, but as this code is, the memory keeps growing.
You can't invoke delete on a void *.
The solution is to not cast a pointer-to-void** (which is what new void*[...] will give you) to void*. I don't really know what your code is supposed to be doing, but have you tried changing the type of DataPtr to void **?
More generally, avoid void* as far as possible in C++. There are better solutions. If you edit your question to describe what you're trying to achieve, then we may be able to help suggest something.
You should try avoid mixing void* and new. In C++ actually, new is meant to automatically determine the type of the pointer; then why should not use it. At least you can use char*, if you are simply dealing with raw bytes.
Other point is new void*[SIZE] allocates void**. So you should change the declaration to void **DataPtr. Remove typecasting ahead of new. You can now delete[] DataPtr;.
Edit:
The code have some problems, the variables should be declared like below:
ColLenArray = new long[NumCols * sizeof(long)]; // declare as long[] (not long())
OffsetArray = new long[NumCols * sizeof(long)];
when you declare those variables as, new long(); it will simply initialize the value and assign a pointer to single long.
The memory corruption happens because, you are using ColLenArray[i], which is accessing wrong memory. Since you are going to use above variables as arrays, it should be new long[]. Then memory corruption will not happen. After usage, you should delete[] them.
You just want a block of memory that you can pass to some database library routines? Allocate thus:
char * buffer = new char[ len ];
len is the length of the buffer in bytes. To delete, simply do:
delete [] buffer;
You want a void* to pass to a function?
void * DataPtr = static_cast< void* >( buffer );
For extra merit points, use boost to manage deletion:
boost::scoped_array< char > buffer( new char[ len ] );
... then you don't have to worry about deletion. To get the buffer here, you need:
void * DataPtr = static_cast< void* >( buffer.get() );

What's the equivalent of new/delete of C++ in C?

What's the equivalent of new/delete of C++ in C?
Or it's the same in C/C++?
There's no new/delete expression in C.
The closest equivalent are the malloc and free functions, if you ignore the constructors/destructors and type safety.
#include <stdlib.h>
int* p = malloc(sizeof(*p)); // int* p = new int;
...
free(p); // delete p;
int* a = malloc(12*sizeof(*a)); // int* a = new int[12];
...
free(a); // delete[] a;
Note that constructors might throw exceptions in C++. The equivalent of player* p = new player(); would be something like this in C.
struct player *p = malloc(sizeof *p);
if (!p) handle_out_of_memory();
int err = construct_player(p);
if (err)
{
free(p);
handle_constructor_error();
}
The equivalent of delete p is simpler, because destructors should never "throw".
destruct(p);
free(p);
Use of new and delete in C++ combines two responsibility - allocating/releasing dynamic memory, and initialising/releasing an object.
As all the other answers say, the most common way to allocate and release dynamic memory is calling malloc and free. You also can use OS-specific functions to get a large chunk of memory and allocate your objects in that, but that is rarer - only if you have fairly specific requirements that malloc does not satisfy.
In C, most APIs will provide a pair of functions which fulfil the other roles of new and delete.
For example, the file api uses a pair of open and close functions:
// C++
fstream* fp = new fstream("c:\\test.txt", "r");
delete fp;
// C
FILE *fp=fopen("c:\\test.txt", "r");
fclose(fp);
It may be that fopen uses malloc to allocate the storage for the FILE struct, or it may statically allocate a table for the maximum number of file pointers on process start. The point is, the API doesn't require the client to use malloc and free.
Other APIs provide functions which just perform the initialisation and releasing part of the contract - equivalent to the constructor and destructor, which allows the client code to use either automatic , static or dynamic storage. One example is the pthreads API:
pthread_t thread;
pthread_create( &thread, NULL, thread_function, (void*) param);
This allows the client more flexibility, but increases the coupling between the library and the client - the client needs to know the size of the pthread_t type, whereas if the library handles both allocation and initialisation the client does not need to know the size of the type, so the implementation can vary without changing the client at all. Neither introduces as much coupling between the client and the implementation as C++ does. (It's often better to think of C++ as a template metaprogramming language with vtables than an OO language)
Not directly an exact replica but compatible equivalents are malloc and free.
<data-type>* variable = (<data-type> *) malloc(memory-size);
free(variable);
No constructors/destructors - C anyway doesn't have them :)
To get the memory-size, you can use sizeof operator.
If you want to work with multidimensional arrays, you will need to use it multiple times (like new):
int** ptr_to_ptr = (int **) malloc(12 * sizeof(int *)); //assuming an array with length 12.
ptr[0] = (int *) malloc(10 * sizeof(int)); //1st element is an array of 10 items
ptr[1] = (int *) malloc(5 * sizeof(int)); //2nd element an array of 5 elements etc
Use malloc / free functions.
Late, but I really like this syntax, although I'm not sure if it fits ways of C
#include <stdlib.h>
#define new(type, length) malloc(sizeof(type)*(length))
#define delete(x) free(x)
int main()
{
int *test = new(int, 30);
delete(test);
}

Am I using new operator correctly?

I have the following pointer.
char **x = NULL;
x is will point to an array of pointers. So is the following code correct?
x = new (nothrow) (*char)[20];
and we will dealocate it using
delete[] x;
Is
x = (char **) malloc(sizeof(char **) * 20);
and
x = new (nothrow) (*char)[20];
equivalent?
Apart from the pointer-syntax mentioned by unwind, it is equivalent: an array of 20 char* will be allocated and deleted in both cases.
C++-adept warning: use std::vector< std::string > instead :) No memory management needed.
No, that code has syntax errors. The asterisk goes after the type name, to form a pointer to that type. So it's:
char*
not:
*char
It's weird that you have this right in the "C-style" example using malloc(), but not in C++.
As many commenters have kindly enough pointed out, there are other issues with the malloc() and its use of sizeof, though. But at least it got the type name right. Personally I'm against repeating type names in malloc() calls if at all possible, so I would write that version like this, to allocate a dynamic array of 20 character pointers:
char **x;
x = malloc(20 * sizeof *x);
This way:
Should be read as "20 times the size of whatever x points at", i.e. 20 times the size of a single char * pointer.
Contains the magical constant 20 in one place only.
Doesn't repeat any part of the type, if you were to change to wchar_t **x this would still work, and not by chance.
Is written in C, since I felt that is more natural when discussing malloc(). In C++, you need to cast the return value. In C, you should never do that.
New was introduced in C++. Malloc is C.
You shouldnt mix and match them... i.e. dont use delete on something you have used malloc on. Check this article.
I'd question why you are allocating such a thing in the first place. In C++, a std::vector of std::string is much more likely to be what you need.