11285

How to convert a C statement using malloc() to C++?

Question:

I have a buffer in C with this code

buffer = malloc(sizeof(uint32_t)*CACHE_LEN*2);

How can I change this line to C++?

Is it better with malloc or with new[]?<br /> I cannot understand the meaning of this sizeof(uint32_t).

Answer1:

The line you mention will compile fine in C++, save for that fact that if buffer is not a void *, then you may need to cast the return value of malloc in C++, which you don't need to do in C (and probably should not do).

EG:

uint32_t *buffer = (uint32_t *) malloc(sizeof(uint32_t)*CACHE_LEN*2);

However, you may wish to convert to a new / delete paradigm; that will require more than just changing that line.

EG:

uint32_t *buffer = new uint32_t[CACHE_LEN*2]; ... delete[] buffer;

If you want to be more C++-like still, then use std::vector or similar:

std::vector<uint32_t> buffer(CACHE_LEN*2);

Answer2:

Assuming that CACHE_LEN is indeed a macro that hides a value that is known at compile time:

auto buffer = make_unique<array<uint32_t, CACHE_LEN*2>>();

This has the fun property that you get pretty much all the advantages of modern C++ at just about zero overhead.

If you wish to stay somewhat closer to your C roots or CACHE_LEN is not known at compile time, you can alternatively use, which removes some features that array provides:

auto buffer = make_unique<uint32_t[]>(CACHE_LEN*2);

Finally, if you want to go all the other way, you can use a fully dynamic array (vector in C++ lingo):

auto buffer = std::vector<uint32_t>(CACHE_LEN*2);

All of the above solutions ensure that resource management is being done by the scope of buffer. The solutions that use make_unique can (more or less) easily be changed to use shared pointers instead.

To stay completely old-school, std::malloc and std::free exist in C++ as well, but malloc requires casting its result to the proper pointer type. They can also be replaced with new uint32_t[CACHE_LEN*2] and delete[] buffer.

P.S.: The meaning of the sizeof(uint32_t) is simply to account for the fact that malloc does not allocate a number of elements, but rather a number of bytes - and most types require more than 1 byte per element.

Answer3:

std::vector<uint32_t> v(CACHE_LEN * 2);

sizeof(type) return the size in chars of the type of the expression passed. For a uint32_t it would be 4.

Answer4:

sizeof() gives the size in byte of the type given between the parenthesis. The type takes sizeof() in memory. This you need to know when you allocate memory to store data in. The CACHE_LEN * 2 depends solely on your usage.

If you need to store five times a pair of uint32_t you use:

malloc( sizeof( uint32_t ) * 2 * 5 );

malloc will allocate a fixed size of memory. This means you can't change the size.

The new/delete is equivalent to malloc/free but in C++. If you use new[] you should use delete[] also.

char buf = new char[ 10 ]; delete[] buf;

The delete[] goes where the life cycle of the allocated memory has ended. If you create it within a function, then the delete[] should be there too. Or you get memory leaks. If you have it at the global scope of a class and you allocate the memory in the constructor, it is an assumption to delete[] the memory in the destructor but is usually the case. It depends on why and when you need the memory. One thing is for sure, if you allocate you need to deallocate (new[]/delete[]).

<blockquote>

Paolo Bolzoni mentioned the use of std::vector

</blockquote>

That's perfectly fine and in most cases very easy to use. If you need to optimize your code for speed, having a fixed size memory block would be faster then a std::vector. It depends on your needs but also your preference.

Answer5:

<blockquote> buffer = malloc(sizeof(uint32_t)*CACHE_LEN*2); </blockquote>

This can be <em>"translated"</em> in C++ in several ways.

But, first it must be clear what this does in C, since you wrote in your question that it's not clear for you the meaning of sizeof(uint32_t).

Using malloc(), you can dynamically (i.e. at <em>run-time</em>) allocate some <strong>contiguous</strong> space from the <em>heap</em>.<br /> The parameter you pass to malloc is the <em>size</em> of the requested space, <strong>in bytes</strong>.<br /> The code you posted seems to allocate CACHE_LEN*2 count of uint32_t elements. Since malloc expects its size parameter to be measured <em>in bytes</em>, you have to multiply CACHE_LEN*2 (the <em>"count"</em> factor) by the size, in bytes, of each element, i.e. of a uint32_t, which is sizeof(uint32_t).

So, you have:

<ul><li>element type: uint32_t</li> <li>element count: CACHE_LEN*2</li> <li>size of each element, in bytes: sizeof(uint32_t)</li> </ul>

So:

<blockquote>

<em>Total size in bytes</em> for malloc() = sizeof(uint32_t) * CACHE_LEN*2

</blockquote>

Now that this malloc() call should be clear, let's move forward to the C++ equivalent.

<hr />

The most immediate "mapping" is from C's malloc() to C++'s <strong>new[]</strong>.

Note that, while malloc requires the size to be expressed in <em>bytes</em>, when you call new[] you can just specify the <strong>element count</strong> (<em>not</em> the <em>raw</em> byte count).

So, a C++ code using new[] would be something like this:

// Allocate (CACHE_LEN*2) elements of type uint32_t uint32_t* buffer = new uint32_t[CACHE_LEN*2];

When you allocate memory using malloc(), you have to free it using free().<br /> The C++ counterpart of new[] is <strong>delete[]</strong>, e.g.:

// Release buffer memory allocated with new[] delete[] buffer; // Avoid dangling references buffer = nullptr;

But there's more. When <strong>memory allocation fails</strong>, malloc just returns NULL. Instead, C++'s new[] <strong>throws an exception</strong> in case of allocation failure. This exception is of type std::bad_alloc. You can catch that somewhare in your code to handle the memory allocation failure case.

If you want a behavior similar to malloc, with failed allocations returning a nullptr pointer, you can use the <strong>std::nothrow</strong> constant with new[], e.g.:

buffer = new (std::nothrow) uint32_t[CACHE_LEN*2]; // On allocation failure, just returns nullptr // (does *not* throw an exception). <hr />

However, in <em>modern C++</em> code, you may want to use a convenient container class to store your contiguous buffer memory. A very common candidate for that is <strong>std::vector</strong>.

std::vector is a class template: you specify the type of the elements as template argument, and you can specify the element count as a constructor parameter, e.g.:

#include <vector> // For std::vector .... std::vector<uint32_t> buffer(CACHE_LEN*2);

Since the default memory allocator for vector uses new[] for allocating memory, in case of allocation failure the above constructor will throw a std::bad_alloc C++ exception.

Note that the memory allocated by a vector is <strong>automatically</strong> released by the vector's <em>destructor</em>. So you don't have to manually release that memory. This helps writing code that is <em>structurally incapable of leaking memory</em> (and other resources).

You can access the items in the vector using its overloaded operator[], just like an ordinary simple raw array (e.g. buffer[i] accesses the i-th item in the buffer; note that indexes are 0-based).

If you want a pointer to the beginning of the vector (which is the strict equivalent of your buffer pointer), you can call vector's <strong>data()</strong> method, e.g.:

// Points to the beginning of vector memory uint32_t* ptr = buffer.data(); // ...use ptr...

Answer6:

With C++, malloc become new/new[] and free become delete/delete[].

Recommend

  • How can I pass the index of a for loop as the argument for pthread_create
  • Fortran array automatically growing when adding a value
  • CHAR vs VARCHAR for password security
  • DOMXML, PHP4 => PHP5
  • textIndicatorPrecision in dojox.dgauges using dojo
  • Netlink sockets and libnl - nl_recvmsgs_default returning -16 (EBUSY)
  • Generating anchors with PyYAML.dump()?
  • What is the reason that Policy.getPolicy() is considered as it will retain a static reference to the
  • Want to understand iframe breakout code
  • Configure Spring's MappingJacksonHttpMessageConverter
  • Getting NullPointer exception with File.listfiles()
  • How to autopopulate a field in SugarCRM form
  • Thread 1: EXC_BAD_ACCESS (code =1 address = 0x0)
  • Object and struct member access and address offset calculation
  • How to assign byte[] as a pointer in C#
  • Convert Type Decimal to Hex (string) in .NET 3.5
  • WPF ICommand CanExecute(): RaiseCanExecuteChanged() or automatic handling via DispatchTimer?
  • How solve “Qt: Untested Windows version 10.0 detected!”
  • C: Incompatible pointer type initializing
  • why xml file does not aligned properly after append the string in beginning and end of the file usin
  • copying resource to sdcard gives a damaged file in android
  • C++ Partial template specialization - design simplification
  • Change multiple background-images with jQuery
  • Is there a javascript serializer for JSON.Net?
  • Java Scanner input dilemma. Automatically inputs without allowing user to type
  • Android screen density dpi vs ppi
  • DirectX11 ClearRenderTargetViewback with transparent buffer?
  • Javascript Callbacks with Object constructor
  • Where to put my custom functions in Wordpress?
  • How can I use Kendo UI with Razor?
  • Change an a tag attribute in JavaScript based on screen width
  • Weird JavaScript statement, what does it mean?
  • How do you troubleshoot character encoding problems?
  • Buffer size for converting unsigned long to string
  • How can I get HTML syntax highlighting in my editor for CakePHP?
  • How do I configure my settings file to work with unit tests?
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • Django query for large number of relationships
  • Binding checkboxes to object values in AngularJs
  • How can i traverse a binary tree from right to left in java?