I would like to perform a deep copy of a char**, but I have no idea how to allocate memory / copy this datatype. This is for a copy constructor in a class that contains a char**. For example, lets say I have this code:
char ** arr1 = new char*[20];
arr1[0] = (char*)"This is index 1";
arr1[1] = (char*)"This is index 2";
char ** arr2;
How do I deep copy the contents of arr1 into arr2? Any help is appreciated!
It’s for a programming assignment, and the teacher wants all strings
to be stored as char*,...
You can tell your teacher that std::string does store strings as char*. If he still doesnt like you to use std::string you should write your own wrapper, because working with bare char* is what you do when you write C, but not in C++. You should write a:
struct my_string {
char* data;
... constructor, operator[], etc...
};
You basically dont need to write more code than you already do, but you should put it in the right place (ie hide it behind a nice interface). You will immediately see the benefit of it when you eg consider ...
...so an array of strings has to be stored as an array of char*.
No. An array of strings is std::array<my_string> (or std::vector<my_string> if it is supposed to be dynamic). And if your teacher insists on not using std::vector, then you should do the same as you just did for strings for vectors (ie encapsulate all the dirty pointer and memory stuff in one place).
This seems more like a C question, but here is an example:
char **AllocateAndDeepCopy(char **arr1, int arr1size)
{
unsigned int i;
char **arr2;
/* Allocate string array */
arr2 = new char*[arr1size];
/* Iterate array elements */
for (i=0; i<arr1size; i++) {
/* Allocate string */
arr2[i] = new char[strlen(arr1[i])+1];
/* Copy contents */
strcpy(arr2[i], arr1[i]);
}
return arr2;
}
Later you have to deallocate arr2 this way:
void DeallocateArr2(char **arr2, int size)
{
for (int i=0; i<size; i++) {
delete arr2[i];
}
delete arr2;
}
I can only shake my head about the sorry state of C++ education. We have a looong way to go there. But since that’s apparently a given, what’s the best you can do?
To copy a C-style data structure like that you have know two things at the point of copy. Both are not inherently provided by a C-style array, so you’ll have to track them explicitely.
The capacity of arr1: 20. If that’s not a compile time constant you have to store it and pass it around. Since you want to implement a copy ctor that means storing the capacity in a non-static member variable of the object.
The number of used indexes in arr1: 2. Same as above. Alternatively make sure that all unused indexes are set to nullptr.
Now you can allocate an arr2 of the correct size and then allocate+memcpy all used indexes.
However, your program will go up in flames regardless, because arr1 and arr2 cannot be treated the same, even though they look identical. The used indexes of arr1 must never ever be deleted because they contain pointers to character literals: They were never newd and live in read-only memory. On the other hand you absolutely must delete the indexes of arr2, because they were newd.
If this brutal disregard of const is really required by the assignment I’d go one step further. I’d introduce another member variable, an array of booleans that tracks which indexes of the char array point to char literals and which were dynamically allocated. During copy you now have all the necessary information to either memcpy or simply set the pointer. Crazy? Definitely, but the whole assignment is, and that way the craziness is visible at least instead of hidden behind an innocent-looking C-style cast. Btw: those should be const_cast<char*> to make it clear what’s going on.
Just take a look at http://en.cppreference.com/w/cpp/algorithm/copy, the deep copy is made by
*d_first++ = *first++;
Related
I am trying to resize a dynamically allocated string array; here's the code!
void resize_array() {
size_t newSize = hash_array_length + 100;
string* newArr = new string[newSize];
fill_n(hash_array,newSize,"0"); //fills arrays with zeros
memcpy( newArr, hash_array, hash_array_length * sizeof(string) );
hash_array_length = newSize;
delete [] hash_array;
hash_array = newArr;
}
unfortunately it isn't working and gives a segmentation fault. any idea why? this is basically a linear probing hash table where the element gets inserted wherever there is a 0 hence I use fill_n to fill the newly created array with 0's. any help please?
memcpy( newArr, hash_array, hash_array_length * sizeof(string) );
This line is extremely dangerous, std::string is not a plain old data type,
you can't make sure that memcpy could initialize it correctly, it may cause
undefined behavior, one of the most nasty behavior of c++(or programming).
Besides, there are a better and safer(in most of the times) solution to create
a dynamic string array in c++, just use vector
//create a dynamic string array with newSize and initialize them with "0"
//in your case, I don't think you need to initialize it with "0"
std::vector<std::string> newArr(newSize, "0");
if the hash_array has the same type as newArr(std::vector)
The way of copy it is very easy.
c++98
std::copy(hash_array.begin(), hash_array.end(), newArr.begin());
c++11
std::copy(std::begin(hash_array), std::end(hash_array), std::begin(newArr));
Better treat c++ as a new language, it has too many things are different from c.
Besides, there are a lot of decent free IDE, like code::blocks and QtCreator
devc++ is a almost dead project.
If you are new to c++, c++ primer 5 is a good book to start.
If string is actually an std::string (and probably even if it isn't) then this will crash. You are creating a new array of strings, copying the old string classes over the top, and then freeing the old strings. But if the string class contains internal pointers to allocated memory this will result in a double free because all you are doing is copying the internal pointers - not making new memory allocations.
Think about it like this; imagine you had the following class:
class foo
{
char* bar;
foo() { bar = malloc(100); }
~foo() { free(bar);
};
foo* ptr1 = new foo;
foo* ptr2 = new foo;
memcpy(ptr2, ptr1, sizeof(foo*));
delete ptr1;
At this point, ptr2->bar points to the same memory that ptr1->bar did, but ptr1 and the memory it held has been freed
The best solution would be to use a std::vector because this handles the resizing automatically and you don't need to worry about copying arrays at all. But if you want to persist with your current approach, you need to change the memcpy call to the following:
for (int i = 0; i < hash_array_length; ++i)
{
newArr[i] = hash_array[i];
}
Rather than just copying the memory this will call the class's copy constructor and make a proper copy of its contents.
I suspect the culprit is memcpy call. string is complicated type which manages the char array by pointers (just as you are doing right now). Normally copying string is done using assignment operator, which for string also copies its own array. But memcpy simply copies byte-per-byte the pointer, and delete[] also deletes the array managed by string. Now the other string uses deleted string array, which is BAAAD.
You can use std::copy instead of memcpy, or even better yet, use std::vector, which is remedy to most of your dynamic memory handling problems ever.
I apologise if I'm completely misunderstanding C++ at the moment, so my question might be quite simple to solve. I'm trying to pass a character array into a function by value, create a new array of the same size and fill it with certain elements, and return that array from the function. This is the code I have so far:
char *breedMutation(char genome []){
size_t genes = sizeof(genome);
char * mutation = new char[genes];
for (size_t a = 0 ;a < genes; a++) {
mutation[a] = 'b';
}
return mutation;
}
The for loop is what updates the new array; right now, it's just dummy code, but hopefully the idea of the function is clear. When I call this function in main, however, I get an error of initializer fails to determine size of ‘mutation’. This is the code I have in main:
int main()
{
char target [] = "Das weisse leid"; //dummy message
char mutation [] = breedMutation(target);
return 0;
}
I need to learn more about pointers and character arrays, which I realise, but I'm trying to learn by example as well.
EDIT: This code, which I'm trying to modify for character arrays, is the basis for breedMutation.
int *f(size_t s){
int *ret=new int[s];
for (size_t a=0;a<s;a++)
ret[a]=a;
return ret;
}
Your error is because you can't declare mutation as a char[] and assign it the value of the char* being returned by breedMutation. If you want to do that, mutation should be declared as a char* and then deleted once you're done with it to avoid memory leaks in a real application.
Your breedMutation function, apart from dynamically allocating an array and returning it, is nothing like f. f simply creates an array of size s and fills each index in the array incrementally starting at 0. breedMutation would just fill the array with 'b' if you didn't have a logic error.
That error is that sizeof(genome); will return the size of a char*, which is generally 4 or 8 bytes on a common machine. You'll need to pass the size in as f does since arrays are demoted to pointers when passed to a function. However, with that snippet I don't see why you'd need to pass a char genome[] at all.
Also, in C++ you're better off using a container such as an std::vector or even std::array as opposed to dynamically allocated arrays (ones where you use new to create them) so that you don't have to worry about freeing them or keeping track of their size. In this case, std::string would be a good idea since it looks like you're trying to work with strings.
If you explain what exactly you're trying to do it might help us tell you how to go about your problem.
The line:
size_t genes = sizeof(genome);
will return the sizeof(char*) and not the number of elements in the genome array. You will need to pass the number of elements to the breedMutation() function:
breedMutation(target, strlen(target));
or find some other way of providing that information to the function.
Hope that helps.
EDIT: assuming it is the number of the elements in genome that you actually want.
Array are very limited.
Prefer to use std::vector (or std::string)
std::string breedMutation(std::string const& genome)
{
std::string mutation;
return mutation;
}
int main()
{
std::string target = "Das weisse leid"; //dummy message
std::string mutation = breedMutation(target);
}
Try replacing the second line of main() with:
char* mutation = breedMutation(target);
Also, don't forget to delete your mutation variable at the end.
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.
I am writing a programm in C++. In my programm I need to create an array with dynamic size inside one function, but this array should be also accessable for other functions. I will not post here my code, just write one dummy example.
char *array;
void function_1() {
array = new char(3);
array[0] = "value 1";
array[1] = "value 2";
array[2] = "value 3";
}
void function_2() {
array[0] = "new value 1";
}
int main() {
function_1();
function_2();
delete[] array;
}
My question is: I am not sure, if the array will exist outside the function_1, where it was initialised, until I delocate a memory of array.
Or the array will have just a behaviour of local variable inside one function. What means, that the memory, which stores the array values, will be dellocated after the function is finished and the memory addresses of my array can be rewroten with something else later in my programm.
Thank you.
First, of course it will exist outside, that's all what dynamic allocation is about. Also, the variable itself is global. Also, it should be a char const** array; and the allocation should be new char const*[3] (note the square brackets). The const because you won't change the contents of the strings here.
Second, don't do that. Just put it in a class and use a std::vector!
#include <vector>
class Foo{
public:
function_1(){
_array.push_back("value 1");
_array.push_back("value 2");
_array.push_back("value 3");
}
function_2(){
_array[0] = ("new value 1");
}
private:
std::vector<std::string> _array;
};
int main(){
Foo f;
f.function_1();
f.function_2();
}
Even better, have a std::vector<std::string>, so you can safely modify the contents without having to worry about memory management. Though, to this won't be a single block any more. Now I got to ask, how exactly do you want to pass the buffer to the socket?
You actually have a fatal error in your function_1(). The following code will cause array to point to a character, with the value 3. Then, it will overwrite various parts of neighboring memory, basically causing a buffer overflow.
void function_1() {
array = new char(3);
array[0] = "value 1";
array[1] = "value 2";
array[2] = "value 3";
}
What you probably want to do is create something like:
char **array;
array = new char*[3];
array[0] = new char[strlen(...)];
array[0] = strncpy(array[0], ..., strlen(...)];
// etc
A much safer and cleaner way of accomplishing this would be to do what Xeo is suggesting, and using a std::vector instead of a plain array.
Since array is global, it is visible to other functions. Memory allocated with new[] stays around until it is freed by delete[].
It will exist and be global, because the char * array pointer is global.
The memory that you allocate in function1 will stay allocated after the program exits the scope of the function and will work as expected in functions 2 and 3. Notice however, that behaviour is undefined if you call functions 2 and 3 before function one. In general though, what you're trying to do here looks like bad design, but for the sake of the question I won't bug you about that now :)
It would greatly improve the clarity of your code if you'd:
use a std::vector, especially if you plan to resize it later
use a std::string to represent strings
pass the array or vector by reference to the functions that need it.
int main() {
std::vector<std::string> vect;
function_1(vect);
function_2(vect);
}
where your functions look like:
void function_1(std::vector<std::string> & Vect)
typedefs help manage the argument types
This way you won't have to worry about leaks as the vector will deallocate itself when out of scope.
I'm in the unfortunate position to write my own vector implementation (no, using a standard implementation isn't possible, very unfortunately). The one which is used by now uses raw bytes buffers and in-place construction and deconstruction of objects, but as a side-effect, I can't look into the actual elements. So I decided to do a variant implementation which uses internally true arrays.
While working on it I noticed that allocating the arrays would cause additional calls of construtor and destructor comapred to the raw buffer version. Is this overhead somehow avoidable without losing the array access? It would be nice to have it as fast as the raw buffer version, so it could be replaced.
I'd appreciate as well if someone knows a good implementation which I could base my own on, or the very least get some ideas from. The work is quite tricky after all. :)
Edit:
Some code to explain it better.
T* data = new T[4]; // Allocation of "num" elements
data[0] = T(1);
data[1] = T(2);
delete[] data;
Now for each element of the array the default constructor has been called, and then 2 assignment methods are called. So instead just 2 constructor calls we have 4 and later 4 destructor calls instead just 2.
as a side-effect, I can't look into the actual elements.
Why not?
void* buffer = ...
T* elements = static_cast<T*>(buffer);
std::cout << elements[0] << std::endl;
Using true arrays means constructors will be called. You'll need to go to raw byte buffers - but it's not too bad. Say you have a buffer:
void *buffer;
Change that to a T *:
T *buffer;
When allocating, treat it as a raw memory buffer:
buffer = (T *) malloc(sizeof(T) * nelems);
And call constructors as necessary:
new(&buffer[x]) T();
Your debugger should be able to look into elements of the buffer as with a true array. When it comes time to free the array, of course, it's your responsibility to free the elements of the array, then pass it to free():
for (int i = 0; i < nInUse; i++)
buffer[x].~T();
free((void*)buffer);
Note that I would not use new char[] and delete[] to allocate this array - I don't know if new char[] will give proper alignment, and in any case you'd need to be careful to cast back to char* before delete[]ing the array.
I find the following implementation quite interesting: C Array vs. C++ Vector
Besides the performance comparison, his vector implementation also includes push/pop operations on the vector.
The code also has an example that shows how to use the macros:
#include "kvec.h"
int main() {
kvec_t(int) array;
kv_init(array);
kv_push(int, array, 10); // append
kv_a(int, array, 20) = 5; // dynamic
kv_A(array, 20) = 4; // static
kv_destroy(array);
return 0;
}