Using memcpy with smart pointers in C++ - c++

I have a smart pointer defined like this
auto ptr = make_shared<int[]>(5);
and another array
int arr[] = {1,2,3,4,5};
I want to copy data in arr to ptr, I tried using this
memcpy(ptr.get(), arr, 5 * sizeof(int))
But when I try printing like this
for (int i = 0; i < 5; i++) {
std::cout<<ptr[i]<<std::endl;
}
I get
malloc(): corrupted top size
Process finished with exit code 134
(interrupted by signal 6: SIGABRT)
Is there something wrong with the ptr initialization ?

Here is an example of what you need (hope so):
#include <iostream>
#include <memory>
#include <cstring>
int main() {
// Create a unique_ptr to an int array
std::unique_ptr<int[]> arr1(new int[5]{ 1, 2, 3, 4, 5 });
// Create a unique_ptr to an int array
std::unique_ptr<int[]> arr2(new int[5]);
// Use memcpy to copy the data from arr1 to arr2
std::memcpy(arr2.get(), arr1.get(), 5 * sizeof(int));
// Print the contents of arr2
for (int i = 0; i < 5; i++) {
std::cout << arr2[i] << " ";
}
std::cout << std::endl;
return 0;
}

Related

Return an array from a function in c++

I'm trying to implement a function that returns an array, I came to this solution, but I don't know if it is a good practice, that's how I did it:
#include <iostream>
using namespace std;
int* returnNewArray(int n) {
int* arr = new int[n];
for (int i=0;i<n;i++)
arr[i] = i;
return arr;
}
int main() {
int n = 5;
int* arr = returnNewArray(n);
for (int i=0;i<n;i++)
cout << arr[i] << "\t";
delete[] arr;
arr = NULL;
cout << endl;
}
I wonder if it is necessary to deallocate the memory that I allocated in the function to create the dynamic array (arr).
I don't know if it is a good practice
It's not. Nowadays, cases where using new/new[] and delete/delete[] are necessary are very few.
I wonder if it is necessary to deallocate the memory that I allocated in the function
It is necessary if you want to avoid memory leaks and since you used a raw owning pointer, you need to do it manually, just like you do in your code. Your code is cleaning up correctly.
Good practice would however be to use a std::vector<int> or at least use a smart pointer like std::unique_ptr<int[]> instead since these will clean up memory automatically when they go out of scope.
vector<int> version:
#include <numeric> // std::iota
#include <vector> // std::vector
std::vector<int> returnNewArray(size_t n) {
std::vector<int> arr(n);
std::iota(arr.begin(), arr.end(), 0); // [0, n)
return arr;
}
unique_ptr<int[]> version:
#include <memory> // std::unique_ptr / std::make_unique_for_overwrite
#include <numeric> // std::iota
std::unique_ptr<int[]> returnNewArray(size_t n) {
auto arr = std::make_unique_for_overwrite<int[]>(n);
std::iota(arr.get(), arr.get() + n, 0); // [0, n)
return arr;
}
Both versions will let you iterate over the result just like you do in your code - and you don't have to delete[] anything when you're done:
auto arr = returnNewArray(n);
for(int i = 0; i < n; ++i)
std::cout << arr[i] << '\t'; // 0 1 2 3 4
But the std::vector<int> has the benefit of knowing its own size and can be used in range based for-loops, which also helps to not accidentally access the array out-of-bounds:
for (int value : arr) // range based for-loop
std::cout << value << '\t'; // 0 1 2 3 4

dynamic allcocation object and int c++

hello I have a doubt how does the code below works??
#include <iostream>
using namespace std;
int main()
{
int* arr = new int;
arr[0] = 94;
arr[1] = 4;
cout << arr[0] << endl;
}
and why does this shows me a error what should I do
#include <iostream>
using namespace std;
struct test
{
int data;
};
int main()
{
test* arr = new test;
arr[0] -> data= 4;
arr[1] -> data= 42;
cout << arr[0]->data << endl;
}
In your code:
#include <iostream>
using namespace std;
int main()
{
int* arr = new int;
arr[0] = 94; // This will work
arr[1] = 4; // This will cause undefined behaviour
cout << arr[0] << endl;
}
Int the above code, arr is a pointer to a single int, so you can access that one int using either:
arr[0]
*arr
..but arr1 won't work as there is not enough memory allocated for the array.
To fix this, you must allocate more memory for arr:
int* arr = new int[2];
..and to change the size of arr:
int arr_size = 2;
int* arr = new int[arr_size]; // size of arr = 2
arr[0] = 12;
arr[1] = 13;
int* new_arr = new int[arr_size + 1];
for (int i = 0; i < arr_size; i++)
{
new_arr[i] = arr[i];
}
delete[] arr;
arr = new_arr;
// size of arr = 3
But all of this gets computationally expensive and time-consuming when arr has a huge number of elements. So I recommend using C++'s std::vector:
Your 2'nd program using std::vector:
#include <iostream>
#include <vector>
struct test
{
int data;
};
int main()
{
std::vector<test> vec{ test(4), test(42) };
std::cout << vec[0].data << std::endl;
}
For more info on std::vector, click here.
Also, consider not using the following line in your code:
using namespace std;
..as it's considered as bad practice. For more info on this, look up to why is "using namespace std" considered as bad practice.

why range base loop doesn't work for arrays in heap, but works for the arrays in stack

Here I'm trying to user c++11 range base loop for tow integer arrays. one declared using new keyword and other not.
#include <iostream>
#include <stdlib.h>
#define ARRAY_LENGTH 100
int main()
{
int* heap_array = new int[ARRAY_LENGTH];
int stack_aray[ARRAY_LENGTH];
for(int i=0; i < ARRAY_LENGTH; i++)
{
int val = (rand() % ARRAY_LENGTH) + 1;
heap_array[i] = val;
stack_array[i] = val;
}
for(int& i : stack_array){ std::cout << i << std::endl;}
for(int& i : *heap_array){ std::cout << i << std::endl;} // compile error
delete[] heap_array;
return 0;
}
Why range base loop doesn't work for the array declared with new keyword? my view is it doesn't matter heap or stack both are heap_array & stack_array are pointers to the first element.
Your heap_array isn't really an array but a raw pointer to an int. A raw pointer does not know anything about the number of elements allocated.

C++: Using dynamic memory allocation to write a function similar to the C realloc() function (i.e. change it's size)

I would like to write a function (changeSize) that uses DMA, where I can choose to change it's (an array's) size to whatever I want, where oldEls is the original size, and newEls is the new size. If newEls is larger than oldEls, I would just add zero's to the end, and if it is smaller than oldEls, I would just truncate. The "ptr" parameter needs to point to the new array. It is my understanding that this would be similar to the C realloc() function.
With the code presently below, I am outputting the following: 0, 0, 3, 6, 0, 0, 0, 0, where the correct output should be 4, 2, 3, 6, 0, 0, 0, 0. I also realize that my show function is maybe not the best function to output the new array, since I have to explicit state the array element size.
Thanks in advance.
#include <iostream>
#include <cstdlib>
using namespace std;
void show( const int a[], unsigned elements );
int * copy( const int a[], unsigned els );
void changeSize( int * & ptr, int newEls, int oldEls );
void die(const string & msg);
int main()
{
int arr[4] = {4, 2, 3, 6};
show(arr, 4);
int * newArr = copy(arr, 4);
cout << endl << endl;
changeSize(newArr, 8, 4);
show(newArr, 8);
}
void show( const int a[], unsigned elements )
{
for (int i = 0; i < elements; i++)
cout << a[i] << endl;
}
int * copy( const int a[], unsigned els )
{
int *newArr;
try
{
newArr = new int[els];
}
catch(const bad_alloc &)
{
die("Copy: Alloc Failure");
}
for (int i = 0; i < els; i++)
newArr[i] = a[i];
return newArr;
}
void changeSize( int * & ptr, int newEls, int oldEls )
{
int * newArr;
try
{
newArr = new int[newEls];
for (int i = 0; i < oldEls; i++)
{
newArr[i] = ptr[i];
}
if (newEls > oldEls)
{
for (int k = oldEls; k < newEls; k++)
newArr[k] = 0;
}
}
catch(const bad_alloc &)
{
die("changeSize: Alloc Failure");
}
ptr = newArr;
delete[] newArr;
}
void die(const string & msg)
{
cerr << "Fatal error: " << msg << endl;
exit(EXIT_FAILURE);
}
First of, you call delete on newArr at the end of changeSize. you need to delete the old value of ptr (that you currently discard). That's (probably) the problem
While I'm at it, I'd like to point your interest to std::vector. It's basically a resizeable array.
Also, copying raw chucks of memory is still best done with memcpy, don't waste your time with writing for loops just to copy ints, do that only for C++ classes.
EDIT: using std::copy is the best solution for C++, it uses memcpy when it can, otherwise it's the same as a for loop copying the objects.
Cheers!

copying a static array to dynamic array

I am defining a dynamic array in c++:
double *values;
int size = 5;
values = new (nothrow) double[size];
I know this works because it compiles, but I see some potential problems.
Say I want to assign values to this array:
double samples = [1,2,3,4,5,6];
values = samples; //runtime error: free or corruption
What exactly is happening to generate this error?
You should use std::copy to copy a static array to a dynamic array like the example below:
#include <iostream>
#include <algorithm>
int main() {
int *a = new int[5];
int b[] = {1, 2, 3, 4, 5};
std::copy(b, b + 5, a);
for(std::size_t i(0); i < 5; ++i) std::cout << a[i] << " ";
std::cout << std::endl;
return 0;
}
LIVE DEMO
Alternatively if you want the convenience of assignments instead of element-wise copying and provided that you know the size of the arrays in compile time and your compiler supports C++11 features, use std::arrays like the example below:
#include <iostream>
#include <array>
int main() {
std::array<int, 5> a;
std::array<int, 5> b {{1, 2, 3, 4, 5}};
a = b;
for(auto i : a) std::cout << i << " ";
std::cout << std::endl;
return 0;
}
LIVE DEMO
However, it is recommend to prefer std::vector over the use of raw dynamic arrays like the example below:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> a(5);
int b[] = {1, 2, 3, 4, 5};
std::copy(b, b + 5, a.begin());
for(auto i : a) std::cout << i << " ";
std::cout << std::endl;
return 0;
}
LIVE DEMO
It doesn't work because you're assigning a static array to a pointer.
double *values;
double samples[] = {1,2,3,4,5,6};
They're two different data types as far as the compiler is concerned.
When you say:
values = new double[size];
You're creating a block of heap (dynamic) memory, and "values" holds the memory address of the first element in the array. To fill in the values from your static array, you need to assign each element individually like so:
values[0] = samples[0];
values[1] = samples[1];
// or better yet
for (int i = 0; i < size; i++)
values[i] = samples[i]
You can use a std::vector which has an iterator constructor, this will solve the problem for you.
std::vector<double> values(std::begin(samples), std::end(samples));
This will ensure the heap memory is properly cleaned up, even in the case of exception, and employs the implementation's debugging machinery to help protect you from events like buffer overflow.