char** memory allocation using new operator - c++

I'm truely baffled by this throwing an error....
char** results = new char*[numRes]; //this is where it breaks
for(int i = 0; i < numRes; i++)
{
results[i] = new char[64];
}
It's throwing a corruption of the heap error. but surely it should work? Im assigning 4 char* to a list of character pointers so I can pass them into functions etc.
I looked around everywhere but they all seem to be showing the malloc and free... Im using them in classes so I want to stick to c++ new and delete.
Could someone lend me a hand please?

What are you doing after you allocate? You only allocated an array of character pointers, you did not allocate space for each element (a pointer). If you try to store items in the elements, you'll run into problems.
For example, if you wanted to store anything in results[0] after your allocation, you would need to allocate to it as well. For example:
results[0] = new char[100]; // NEED TO ALLOCATE BEFORE WRITING TO results[0]!
strcpy(results[0], "Test");
You cannot just copy to results[0] without the allocation. The same holds for any element of results.

You are allocating memory for a pointers array. After that you have to allocate memory for every pointer in your array. I think your code should be like this:
int numRes = 4;
char** results = new char*[numRes];
for(int i=0; i<numRes; i++)
{
results[i] = new char;
}

If using c++ is it possible to use STL? specifically std::string, and std::list or std::vector classes in your code? Unlike traditional c-strings, which are mere sequences of characters in a memory array, C++ string objects belong to a class with many built-in features to operate with strings in a more intuitive way and with some additional useful features common to C++ containers.
#include <string>
#include <list>
std::list<std::string> results; // create a list of strings
// and populate it
results.push_back("blah");
results.push_back("blah1");
results.push_back("blah2");
...

Related

How can we modify the size of array in C++?

I have an array of characters allocated with new and i want to modify the size of the array. Can i use realloc function for that? What is the best way to do so?
No, you can't... realloc() can only be used with malloc()/free()
Best call for a new[] allocated array is to create a new one and then memcpy() the data from one to another.
Better way - use an std::vector or std::string instead of array if you know you'll need resizing. Internally they're pretty much the same array.
In C++ it is best to use the STL std::vector class for this kind of thing. Either that, or a std::string.
I have an array of characters allocated with new and i want to modify the size of the array.
You can't resize an array, you can only allocate a new, larger one, move the contents to the new array, and delete the old one.
Can i use realloc function for that?
If you used malloc to allocate the original array, yes. But that's usually a bad idea in C++, where you usually want to deal with arrays of non-trivial objects not raw memory.
What is the best way to do so?
Use std::string (or perhaps std::vector<char>) to manage a dynamic array of characters automatically. These also have the advantage of using RAII to reduce the risk of memory leaks and other memory management errors.
You can use realloc(), if your array is allocated dynamically(via malloc/calloc/realloc). If you have static array, you can't resize it.If you have allocated with new:
int* Copy = new int[newSize];
std::copy(oldCopy,oldCopy+size,Copy);
But the best way would be to use std::vector<type> from c++ standard library
As was said by others, you cannot resize the array that was allocated per se, but you can create a larger one, copy the content of the first array to the second and delete the first one.
Here's an example, using std::copy().
int main(int argc, char** argv) {
int* arr = new int[5];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
int* tmp = new int[10];
std::copy(arr, arr + 5, tmp);
std::copy(arr, arr, tmp + 5);
delete[] arr;
arr = tmp;
for(int i = 0; i < 10; i++) {
std::cout << arr[i] << "\n";
}
delete[] arr;
std::cin.get();
return 0;
}
This first creates an integer array and fills it. It then creates a larger array and fills it with the content of the first array twice and display that new larger array.
The principle is the same for an array of characters.
As the others have mentionned, your best bet in C++ is to use the standard library. For a resizable array of characters, you should probably use std::string or a vector of strings, but it's a bit overkill in some situations.

Assigning dynamically allocated array of pointers

Having a lot of trouble with this after sifting through many posts on here. Everything compiles but I get a crash right here during this function which should be dynamically allocating the addresses of one array into this array of pointers. I see one or two memory addresses posted so I'm not sure why it would be crashing during the middle of this.
string *copyArray(string ptrArray[],int sizeArray)
{
string **dynamString = new string*[sizeArray];
int i;
for (i=0;i<=sizeArray;++i)
{
(*dynamString[i]) = ptrArray[i];
cout << dynamString[i];
}
return *dynamString;
}
from main I have:
string *arrPtr;
and the function call
arrPtr = copyArray(arrayOfStrings, arraySize);
for (i=0;i<=sizeArray;++i)
accesses an element behind the array yielding an undefined behavior. Elements are indexed from 0 to sizeArray - 1. Another problem is that you allocate the array of pointers:
string **dynamString = new string*[sizeArray];
and then you are derefencing these pointers although they do not point to any object yet:
(*dynamString[i]) = ptrArray[i];
which also causes an undefined behavior. In case you wanted to create a deep copy, you should allocate the memory for every object as well:
for (i = 0; i < sizeArray; ++i)
{
dynamString[i] = new std::string(ptrArray[i]);
cout << *dynamString[i];
}
However you should avoid using C-style arrays always when it is possible and prefer STL containers instead. In this case it could be neat std::vector<std::string> and its constructor that would do the same than your function (just in safer and more reasonable manner with no possible memory leaks):
std::vector<std::string> myStrings(arrayOfStrings, arrayOfStrings + arraySize);
ok I fixed it here. My pointer syntax was incorrect. Here is the correct syntax.
dynamString[i] = &ptrArray[i];

C++ Allocation of array of struct

I have to allocate in C++ an array of struct, any struct contains two vector of int. This is my struct:
typedef struct _Sample{
vector<int> contourX;
vector<int> contourY;
}Sample;
To allocate this array I write the following code:
data = (struct _Sample*) malloc(sizeof(struct _Sample) * nsamples);
When I try to assign a Sample element to data[0] I have an error a runtime. Where is the problem?
You are trying to create an array, for that, you should use new[] to allocate the memory (and delete [] to deallocate it).
That way your code should be:
Sample* data = new Sample[nsamples];
Then you can iterate over each element of your array like any array:
for(int i = 0; i < nsamples; i++)
{
data[i].contourY // do something
data[i].contourX // do something
}
Rule of thumb: Never use malloc in C++.1 It's a C function, and as such, doesn't do all the C++ stuff like calling constructors.
If you must dynamically allocate memory, use new instead.
1. This is a rule with a few exceptions, but for most cases is safe to treat as a blanket rule.
You need to use new - the constructors for your vectors need to be executed.
if you are programming in c++ you could use "new"...like:
_Sample* data = new _Sample[size];

C++ Allocate Memory Without Activating Constructors

I'm reading in values from a file which I will store in memory as I read them in. I've read on here that the correct way to handle memory location in C++ is to always use new/delete, but if I do:
DataType* foo = new DataType[sizeof(DataType) * numDataTypes];
Then that's going to call the default constructor for each instance created, and I don't want that. I was going to do this:
DataType* foo;
char* tempBuffer=new char[sizeof(DataType) * numDataTypes];
foo=(DataType*) tempBuffer;
But I figured that would be something poo-poo'd for some kind of type-unsafeness. So what should I do?
And in researching for this question now I've seen that some people are saying arrays are bad and vectors are good. I was trying to use arrays more because I thought I was being a bad boy by filling my programs with (what I thought were) slower vectors. What should I be using???
Use vectors!!! Since you know the number of elements, make sure that you reserve the memory first (by calling myVector.reserve(numObjects) before you then insert the elements.).
By doing this, you will not call the default constructors of your class.
So use
std::vector<DataType> myVector; // does not reserve anything
...
myVector.reserve(numObjects); // tells vector to reserve memory
You can use ::operator new to allocate an arbitrarily sized hunk of memory.
DataType* foo = static_cast<DataType*>(::operator new(sizeof(DataType) * numDataTypes));
The main advantage of using ::operator new over malloc here is that it throws on failure and will integrate with any new_handlers etc. You'll need to clean up the memory with ::operator delete
::operator delete(foo);
Regular new Something will of course invoke the constructor, that's the point of new after all.
It is one thing to avoid extra constructions (e.g. default constructor) or to defer them for performance reasons, it is another to skip any constructor altogether. I get the impression you have code like
DataType dt;
read(fd, &dt, sizeof(dt));
If you're doing that, you're already throwing type safety out the window anyway.
Why are you trying to accomplish by not invoking the constructor?
You can allocate memory with new char[], call the constructor you want for each element in the array, and then everything will be type-safe. Read What are uses of the C++ construct "placement new"?
That's how std::vector works underneath, since it allocates a little extra memory for efficiency, but doesn't construct any objects in the extra memory until they're actually needed.
You should be using a vector. It will allow you to construct its contents one-by-one (via push_back or the like), which sounds like what you're wanting to do.
I think you shouldn't care about efficiency using vector if you will not insert new elements anywhere but at the end of the vector (since elements of vector are stored in a contiguous memory block).
vector<DataType> dataTypeVec(numDataTypes);
And as you've been told, your first line there contains a bug (no need to multiply by sizeof).
Building on what others have said, if you ran this program while piping in a text file of integers that would fill the data field of the below class, like:
./allocate < ints.txt
Then you can do:
#include <vector>
#include <iostream>
using namespace std;
class MyDataType {
public:
int dataField;
};
int main() {
const int TO_RESERVE = 10;
vector<MyDataType> everything;
everything.reserve( TO_RESERVE );
MyDataType temp;
while( cin >> temp.dataField ) {
everything.push_back( temp );
}
for( unsigned i = 0; i < everything.size(); i++ ) {
cout << everything[i].dataField;
if( i < everything.size() - 1 ) {
cout << ", ";
}
}
}
Which, for me with a list of 4 integers, gives:
5, 6, 2, 6

how to grow a dynamic array of char pointers (in C++)?

I am trying to work with an array of char pointers.
Let's say I dynamically declare such an array like so:
int numrows=100;
char** array = new char*[numrows];
And then I populate it by using getline to get strings from a file, converting the strings to char arrays, then setting a pointer in my array to point to said char array like so:
string entry;
int i=0;
while (getline(file,entry)){
char* cstring = new char[entry.length()];
array[i]=strncpy(cstring,entry.c_str(),entry.length());
free(cstring);
i++;
}
(this works, but is there a better way to do this?)
The problem is, I don't know how to grow the array once i becomes greater than numrows.
I know how to do this for a single-dimensional array, but the two-dimensionality is throwing me off.
I'm thinking I should be able to grow it the way you would grow a single-dimension array, right?
if (i==numrows){
char** temp = new char*[numrows+numrows];
for (int j=0;j<i;j++){
char* cstring = new char[strlen(array[i])];
temp[i]=strncpy(cstrin,array[i],strlen(array[i]));
free(cstring);
}
delete [] array;
array = temp;
}
So if the current array becomes full, make a second array that is twice the size of the current array and fill it with the contents of the current array. Then delete array and let array point to temp. I'm fine up to making temp the new array. I can get the contents of array into temp, but when I delete array and set array = temp, the contents of array aren't the contents of temp.
So my question is how can/should I be growing this dynamic array of char pointers?
use std::vector - it is your friend
std::vector<std::string> arr;
while(getline(file, entry))
{
arr.push_back(entry);
}
done
sort can be done using vector sort with custom compare
bool less3(const std::string &s1, const std::string &s2)
{
return s1.compare(0, 3, s2, 0, 3) == 0;
}
std::sort(arr.begin(), arr.end(), less3);
I bet that less3 could be made more efficient but readability wins unless you really suffer
edit fixed as per nice comment from gman
Apart from the remarks by Tyler McHenry, and the fact that you should use the STL, the problem is most likely that you are freeing each cstring after having copied it. Perhaps you intended to free the original string instead?
for (int j=0;j<i;j++){
char* cstring = new char[strlen(array[i])];
temp[i]=strncpy(cstring,array[i],strlen(array[i]));
delete[] array[i];
}
When you first populate the array, DO NOT call free() on the string. First of all, you should use delete[], but more importantly, you still want to access that string later, right?
now i see you say that this is a class that does allow you to use STL. A class teaching c++ that forbids one of the major language features! - anyway passing along
You do not need to be copying the strings to resize the array , you just need to copy the pointers.
if (i==numrows){
char** temp = new char*[numrows+numrows];
for (int j=0;j<i;j++){
temp[j]=array[j];
}
delete [] array;
array = temp;
}
i am sure there are still out by ones there - left as homework