Functions for dynamic memory allocation in C++ - c++

I'm trying to set up some generic functions in C++ to allocate memory dynamically, and this is what I got to so far:
char* init_char(uint64_t A, const char* init){
char* ptr = new char[A];
memset(ptr, '\0', A*sizeof(char));
if(init != NULL)
strcpy(ptr, init);
return ptr;
}
char** init_char(uint64_t A, uint64_t B, const char* init){
char** ptr = new char*[A];
for(uint64_t a = 0; a < A; a++)
ptr[a] = init_char(B, init);
return ptr;
}
The idea is that you just pass the dimensions (A, B) and the initialization string (init) and it return an array with all the memory allocated. However, while the first one seems to work properly, the second one returns a NULL pointer.
I've looked around but no good. Actually in some other post (Function for Dynamic Memory allocation) they seem to do something quite similar. Am I missing something here?
thanks,

your error is not to use c++.
your problem can be reduced to:
std::string initStr("initialitation string");
int a = 10;
std::vector<std::string> myStringArray(a, initStr);

Related

How to initialize a constant array in heap memory using C++?

In C++, we can allocate heap memory for a dynamic array, but how can we initialize it if it's a read only array? Here is an example:
const char* str = new char[3];
After operating this statement, the system seems to initialize variable str with garbage value implicitly which means i cannot change its value since it has a constant qualifier. So how can i creat a constant string in heap memory and intialize it explicitly?
If i want to creat a object in heap memory, i need a pointer to the object. But if it's constant, i cannot even change it with the pointer after its creation in heap memory. So it became a vicious circle for me.
You can start with char * modify the array, then convert it to const char *:
char *str = new char[3];
// str[i] = ...
const char *cstr = str;
But unless you're trying to practice dynamic memory management, none of this should be necessary. Just use std::string or std::vector<char>.
Your operator new call doesn't allocate const memory. It gets converted to const when you assign it to the variable. The solution is to make a temporary variable that's not const, write the data to it and then finally convert it to a const pointer:
#include <cstring>
#include <memory>
std::unique_ptr<const char[]> PutBytesOntoHeap(const char* data, size_t size)
{
std::unique_ptr<char[]> result(new char[size]);
memcpy(result.get(), data, size);
return result;
}
In current c++ avoid calling new/delete explicitly, only use it internally in datastructures (and even then std::make_unique is prefered). So use std::vector (or alternatively std::string/std::string_view)
#273K Also note most C++ books (teachers, online material) are out of date.
#include <vector>
int main()
{
std::vector<char> str{ 'a', 'b', 'c' }; // this will do the memory allocation for you
// for local use (when a legacy api needs a pointer, otherwise don't use)
const char* ptr = str.data();
return 0;
// std::vector goes out of scope
// will free the allocated memory (so you can't forget to call delete[])
}
if it's constant, i cannot even change it with the pointer after its creation in heap memory
In
const char* str = new char[3];
you actually create a non-const char array and assign it to a const char*. You could just assign it to a char* instead, make the changes you want and then return a const char*. Example:
auto str = []() -> const char* {
char* rv = new char[3];
rv[0] = '1';
rv[1] = '2';
rv[2] = '\0';
return rv;
}();
how can i creat a constant string in heap memory and intialize it explicitly?
You use new const char[] with an initializer:
auto str = new const char[3]{'1', '2', '\0'};
A helper function could look like this:
#include <cstddef>
#include <iostream>
#include <utility>
template <std::size_t N>
auto make_const_cstring(const char (&s)[N]) {
return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
return new const char[N]{s[Is]...};
}(std::make_index_sequence<N>());
}
int main() {
auto str = make_const_cstring("Hello world");
std::cout << str << '\n';
delete[] str;
}
If you want to use an array after the function that created it returns, allocate that array in the heap, not in the run-time stack. Expression new T[size] allocates a new array with size variables in it, each of type T. Remember that an array is treated just like a pointer to the first thing in the array. So expression new int[25] has type int*. Statement
int* A = new int[25];
allocates a new array of 25 ints and stores a pointer to the first one into variable A.
The size can be given by any expression that yields an integer. For example, if you already have an integer variable called n that currently holds 50, then
double* B = new double[n];
allocates an array of 50 doubles.

How do I free the memory occupied by variable that is being returned (using C++, in a class, destructor)?

Example code:
class Myclass
{
char * function(const char *x, const char *y)
{
char *a, *b, *c;
*a = strdup(x);
*b = strdup(y);
*c = (char *) malloc(strlen(a) + strlen(b) + 1);
...
...
free(a);
free(b);
return c;
}
};
How do I free the memory occupied by c? When I try to do it in the destructor, it says use of undeclared identifier c.
Is there anyway to free the memory without allocating the memory in a constructor?
A class destructor should only be responsible for freeing the memory allocated by constructors for that class. That's what is ownership.
Also, c in your code is local to function so it ceases to exist beyond that function i.e a sure shot memory leak unless you are returning c from this function and making sure that caller calls delete/free on that memory. But this puts much burden on usability department.
answer: stop!
and remember you're writing in c++ where the correct thing to do is leave memory management to the standard library and return values rather than pointers.
class Myclass
{
std::string function(const char *x, const char *y)
{
// no more overhead than strdup - and much safer!
std::string a(x), b(y);
// what I shall return
std::string c;
// un-necessary, but can improve efficiency
c.reserve(a.size() + b.size());
// perform my complex string algorithm
//... for example, concatenate into c:
c = a + b;
// return my result
return c;
}
};
now call like so:
{
MyClass x;
auto s = x.function("hello", "world");
// s is a std::string. if I *really* want a pointer, I can...
const char* p = s.c_str();
// note: no need to free *anything*
}
You cannot call free(c); in the destructor unless c is a member variable, which is what the compiler is telling you.
In this case, you have to make sure that the caller of MyClass::function calls free on the returned value.

How to delete 2D Array after its modified by a function?

So, I've made a function that looks like this:
const char **myFunction(char *string)
{
char *bufCopy = new char[strlen(string)];
strcpy(bufCopy,string);
char *tmp = func1(bufCopy);
const char **RetVector = new const char* [6];
RetVector[0] = tmp;
return RetVector;
}
func1 (that is strtok) modified the first argument, so when I delete[] it gives me heap corruption. What could I do?
You must always keep track of the original allocation of your bufCopy, only that one can be deleted. tmp probably only points to part of it (inside the buffer somewhere), so you can't delete it.

Looking at the C++ new[] cookie. How portable is this code?

I came up with this as a quick solution to a debugging problem - I have the pointer variable and its type, I know it points to an array of objects allocated on the heap, but I don't know how many. So I wrote this function to look at the cookie that stores the number of bytes when memory is allocated on the heap.
template< typename T >
int num_allocated_items( T *p )
{
return *((int*)p-4)/sizeof(T);
}
//test
#include <iostream>
int main( int argc, char *argv[] )
{
using std::cout; using std::endl;
typedef long double testtype;
testtype *p = new testtype[ 45 ];
//prints 45
std::cout<<"num allocated = "<<num_allocated_items<testtype>(p)<<std::endl;
delete[] p;
return 0;
}
I'd like to know just how portable this code is.
It is not even remotely portable.
An implementation can perform heap bookkeeping however it wants and there is absolutely no way to portably get the size of a heap allocation unless you keep track of it yourself (which is what you should be doing).
You can globally overload new/delete operators on array, and put the size into the memory area. You get a portable solution.
The below code shows how:
void * operator new [] (size_t size)
{
void* p = malloc(size+sizeof(int));
*(int*)p = size;
return (void*)((int*)p+1);
}
void operator delete [] (void * p)
{
p = (void*)((int*)p-1);
free(p);
}
template<typename T>
int get_array_size(T* p)
{
return *((int*)p-1)/sizeof(T);
}
int main(int argc, char* argv[])
{
int* a = new int[200];
printf("size of a is %d.\n", get_array_size(a));
delete[] a;
return 0;
}
Result:
size of a is 200.
Not portable. But why not use std::vector? Then you can ask it directly how many elements it contains, and you won't need to worry about memory management and exception safety.

Dynamically allocate C struct?

I want to dynamically allocate a C struct:
typedef struct {
short *offset;
char *values;
} swc;
Both 'offset' and 'values' are supposed to be arrays, but their size is unknown until runtime.
How can I dynamically allocate memory for my struct and the struct's arrays?
swc *a = (swc*)malloc(sizeof(swc));
a->offset = (short*)malloc(sizeof(short)*n);
a->values = (char*)malloc(sizeof(char)*n);
Where n = the number of items in each array and a is the address of the newly allocated data structure. Don't forget to free() offsets and values before free()'ing a.
In C:
swc *s = malloc(sizeof *s); // assuming you're creating a single instance of swc
if (s)
{
s->offset = malloc(sizeof *(s->offset) * number_of_offset_elements);
s->values = malloc(sizeof *(s->values) * number_of_value_elements);
}
In C++:
try
{
swc *s = new swc;
s->offset = new short[number_of_offset_elements];
s->values = new char[number_of_value_elements];
}
catch(...)
{
...
}
Note that in C++, you might be better off using vectors as opposed to dynamically allocated buffers:
struct swc
{
std::vector<short> offset;
std::vector<char> values;
};
swc *a = new swc;
Question: is values supposed to be an array of individual characters or an array of strings? That would change things a bit.
EDIT
The more I think about it, the less satisfied I am with the C++ answer; the right way to do this sort of thing in C++ (assuming you need dynamically allocated buffers as opposed to vectors, which you probably don't) is to perform the memory allocation for offset and values as part of a constructor within the struct type, and have a destructor deallocate those elements when the struct instance is destroyed (either by a delete or by going out of scope).
struct swc
{
swc(size_t numOffset = SOME_DEFAULT_VALUE,
size_t numValues = SOME_OTHER_DEFAULT_VALUE)
{
m_offset = new short[numOffset];
m_values = new char[numValues];
}
~swc()
{
delete[] m_offset;
delete[] m_values;
}
short *m_offset;
char *m_values;
};
void foo(void)
{
swc *a = new swc(10,20); // m_offset and m_values allocated as
// part of the constructor
swc b; // uses default sizes for m_offset and m_values
...
a->m_offset[0] = 1;
a->m_values[0] = 'a';
b.m_offset[0] = 2;
b.m_values[0] = 'b';
...
delete a; // handles freeing m_offset and m_values
// b's members are deallocated when it goes out of scope
}
You have to do it seperately. First allocate the struct, then the memory for the arrays.
In C:
swc *pSwc = malloc(sizeof(swc));
pSwc->offset = malloc(sizeof(short)*offsetArrayLength);
pSwc->values = malloc(valuesArrayLength);
In C++, you shouldn't be doing anything like that.
In C:
typedef struct
{
short *offset;
char *values;
} swc;
/// Pre-Condition: None
/// Post-Condition: On failure will return NULL.
/// On Success a valid pointer is returned where
/// offset[0-n) and values[0-n) are legally de-refrancable.
/// Ownership of this memory is returned to the caller who
/// is responsible for destroying it via destroy_swc()
swc *create_swc(unsigned int size)
{
swc *data = (swc*) malloc(sizeof(swc));
if (data)
{
data->offset = (short*)malloc(sizeof(short)*n);
data->values = (char*) malloc(sizeof(char) *n);
}
if ((data != NULL) && (size != 0) && ((data->offset == NULL) || (data->values == NULL)))
{
// Partially created object is dangerous and of no use.
destroy_swc(data);
data = NULL;
}
return data;
}
void destroy_swc(swc* data)
{
free(data->offset);
free(data->values);
free(data);
}
In C++
struct swc
{
std::vector<short> offset;
std::vector<char> values;
swc(unsigned int size)
:offset(size)
,values(size)
{}
};
You will need a function to do this.
Something like (my C/C++ is rusty)
swc* makeStruct(int offsetCount, int valuesCount) {
swc *ans = new swc();
ans->offset = new short[offsetCount];
ans->values = new char[valuesCount];
return ans;
}
myNewStruct = makeStruct(4, 20);
Syntax may be a bit off but that is generally what you are going to need. If you're using C++ then you probably want a class with a constructor taking the 2 args instead of the makeStruct but doing something very similar.
One thing to add to the many correct answers here: you can malloc an over-sized structure to accommodate a variable sized array in the last member.
struct foo {
short* offset;
char values[0]
};
and later
struct *foo foo1 = malloc(sizeof(struct foo)+30); // takes advantage of sizeof(char)==1
to get room for 30 objects in the values array. You would still need to do
foo1->offsets = malloc(30*sizeof(short));
if you want them to use the same size arrays.
I generally wouldn't actually do this (maintenance nightmare if the structure ever needs to expand), but it is a tool in the kit.
[code here in c. You'll need to cast the malloc's (or better use new and RAII idioms) in c++]
swc* a = malloc(sizeof(*a));
a->offset = calloc(n, sizeof(*(a->offset)));
a->values = calloc(n, sizeof(*(a->values)));
You should not cast void* in c... in c++ you must!
Use malloc function or calloc to allocate memory dynamically .
and search it on google to get examples.
The calloc function initializes allocated memory to zero.
Since nobody has mentioned it yet, sometimes it is nice to grab this chunk of memory in one allocation so you only have to call free() on one thing:
swc* AllocSWC(int items)
{
int size = sizeof(swc); // for the struct itself
size += (items * sizeof(short)); // for the array of shorts
size += (items * sizeof(char)); // for the array of chars
swc* p = (swc*)malloc(size);
memset(p, 0, size);
p->offset = (short*)((char*)swc + sizeof(swc)); // array of shorts begins immediately after the struct
p->values = (char*)((char*)swc + sizeof(swc) + items * sizeof(short)); // array of chars begins immediately after the array of shorts
return p;
}
Of course this is a bit more difficult to read and maintain (especially if you dynamically resize the arrays after it is first allocated). Just an alternative method I've seen used in a number of places.
Most of the answers are correct. I would like to add something that you haven't explicitly asked but might also be important.
C / C++ arrays don't store their own size in memory. Thus, unless you want offset and values to have compile-time defined values (and, in that case, it's better to use fixed-size arrays), you might want to store the sizes of both arrays in the struct.
typedef struct tagswc {
short *offset;
char *values;
// EDIT: Changed int to size_t, thanks Chris Lutz!
size_t offset_count;
size_t values_count; // You don't need this one if values is a C string.
} swc;
DISCLAIMER: I might be wrong. For example, if all offsets of all swc instances have the same size, it would be better to store offset_count as a global member, not as a member of the struct. The same can be said about values and values_count. Also, if values is a C string, you don't need to store its size, but beware of Schlemiel the painter-like problems.
You want to use malloc to allocate the memory, and probably also sizeof() to allocate the correct amount of space.
Something like:
structVariable = (*swc) malloc(sizeof(swc));
Should do the trick.
In addition to the above, I would like to add freeing up the allocated memory as below.,
typedef struct {
short *offset;
char *values;
} swc;
swc* createStructure(int Count1, int Count2) {
swc *s1 = new swc();
s1->offset = new short[Count1];
s1->values = new char[Count2];
return s1;
}
int _tmain(int argc, _TCHAR* argv[])
{
swc *mystruct;
mystruct = createStructure(11, 11);
delete[] mystruct->offset;
delete[] mystruct->values;
delete mystruct;
return 0;
}
**If** you will not be resizing the arrays, then you can get away with a single call to malloc().
swc *new_swc (int m, int n) {
swc *p;
p = malloc (sizeof (*p) + m * sizeof (p->offset[0]) + n * sizeof (p->values[0]);
p->offset = (short *) &p[1];
p->values = (char *) &p->offset[m];
return p;
}
You can then free it with a single call to free().
(In general, there are alignment considerations to take into account, but for an array of shorts followed by an array of chars, you will be fine.)