Segmentation Fault to Deallocate the Memory [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last month.
Improve this question
I have received the Segmentation Fault (Segfault) because of the free() function in the following code.
How the free() function can be used in this code without receiving the Segmentation Fault?
#include <iostream>
#include <cstring>
using namespace std;
void driver_01(int* buf1, int buf1_size) {
int* buf2 = (int*)malloc(buf1_size);
//int* buf2 = new int(buf1_size);
memcpy(&buf2, &buf1, buf1_size);
int count = 0;
for (int i = 0; i < buf1_size; i++) {
if (*(buf2 + i) != 0) {
count++;
}
cout << *(buf2 + i) << endl;
}
cout << "Size of buf2: " << count << endl;
free(buf2);
}
int main() {
int buf1[8] = { 2, 6, 12, 15, 22, 30, 40, 50 };
int buf1_size = sizeof(buf1) / sizeof(buf1[0]);
cout << "Size of buf1: " << buf1_size << endl;
driver_01(buf1, buf1_size);
return 0;
}
Output:
Size of buf1: 8
2
6
12
15
22
30
40
50
Size of buf2: 8
Segmentation fault

Your use of malloc() and memcpy() are both wrong.
You are not allocating enough memory for the buf2 array to copy the values from the buf1 array. You are allocating space for only 8 bytes, not 8 ints.
You are copying 8 bytes, not 8 ints, from the wrong source memory address (the address of the buf1 parameter itself rather than the address of the array it points at), and writing them to the wrong destination memory address (the address of the buf2 variable itself rather than the address of the array it points at), thus you are corrupting memory.
Try this instead:
void driver_01(int* buf1, int buf1_size) {
int* buf2 = (int*) malloc(sizeof(int) * buf1_size);
//int* buf2 = new int[buf1_size];
memcpy(buf2, buf1, sizeof(int) * buf1_size);
//std::copy_n(buf1, buf1_size, buf2);
int count = 0;
for (int i = 0; i < buf1_size; i++) {
if (buf2[i] != 0) {
++count;
}
cout << buf2[i] << endl;
}
/*
int count = count_if(buf2, buf2 + buf1_size,
[](int i){ return i != 0; });
for_each(buf2, buf2 + buf1_size,
[](int i){ cout << i << endl; });
*/
cout << "Size of buf2: " << count << endl;
free(buf2);
//delete[] buf2;
}

your actual problem is here
memcpy(&buf2, &buf1, buf1_size);
you mean
memcpy(buf2, buf1, buf1_size);
but as other have said, you must not use malloc or free in c++, you should use new and delete. but in this caese you should use std::vector
Edit. Your malloc is wrong too (thanks Remy). You need
malloc(sizeof(int) * buf1_size)

Related

C++ delete[] array; [duplicate]

This question already has answers here:
C++ after delete pointer
(4 answers)
Closed 6 months ago.
#include <iostream>
#include <string>
using namespace std;
void print(string data[], int size) {
cout << "Print array" << endl;
for (int i=0; i<size; i++) {
cout << data[i] << ", ";
}
cout << endl;
}
int main(int argc, char** argv) {
string arr1[] = {"Apple", "Banana", "Coconut", "Durian"};
string *arr2 = new string[6];
arr2[4] = "Eggplant";
arr2[5] = "AppleBanana";
std::copy(std::begin(arr1), std::end(arr1), arr2);
print(arr2, 6);
delete[] arr2;
print(arr2, 6);
return 0;
}
I was wondering why delete[] arr2; only free up the arr2[0] because after I print it again only the first element in arr2 is freed but the rest still got the elements
I don't quite understand the free()/delete yet so it would be nice if someone also help explain it. I have been asking professor about it and I'm still confused as to why freeing up arr2 still got elements in its
Maybe, it is better to delete array in this way
for(int i = 0; i < size; i++)
{
delete [] arr2[i];
arr2[i] = nullptr;
}
Also you are not allowed to use the deleted arr2 after you used the keyword delete because it will cause some problems in time of and after compilation

return a dynamically allocated array of the same length but with the elements in the reverse order

Write a function, reverseArray, that when passed an int array of length greater than 0 will return a dynamically allocated array of the same length but with the elements in the reverse order. For example, if passed the array, {1,2,3,4,5,6,7,8,9,0} the function would return the array {0,9,8,7,6,5,4,3,2,1}.
Below is my code, but there is a bug in it.
This is my output.
1
2
3
4
5
6
4113
6
5
4
3
2
1
0x7fffe697ceb0
The 4113 and address are provided by the compiler.
#include <iostream>
using namespace std;
int * readNumbers() {
int * a = new int[6];
for (int i = 0; i < 6; i++) {
int x;
cin >> x;
a[i] = x;
}
// a++;
return a;
delete[] a;
}
int *reverseArray(int *numbers1,int length) {
for (int i = length; i >=0; i--) {
cout << numbers1[i] << endl;
}
return numbers1;
delete [] numbers1;
}
int main() {
int *arr1 = readNumbers();
cout << reverseArray(arr1,6) << endl;
return 0;
}
I think there may have been an issue with your wording. Assuming you want your function just to print the reverse of a passed array, you're off to a good start.
One issue is what was said in the comments: your for loop is indexing past your array. When you type int * a = new int[6]; you are creating a pointer 'a' which points to a location in memory. Since you chose size 6, the appropriate amount of memory is allocated. If you happen to index outside of that range, you will end up pointing to a random spot in memory, not allocated for your array. Hence why you are getting a weird number '4113'.
A fix for this could be:
int i = length changed to int i = length-1
Another issue is that your function returns an integer pointer, and you are trying to cout this pointer. As another commenter said, you have to think about what this does. If you try this code:
#include <iostream>
using namespace std;
int main() {
int arr[] = {1, 2, 3};
cout << arr << endl;
return 0;
}
your output would be something like 0xff09ba. This represents the location of the start of the array in memory. If you change arr to (arr + 1) you will get the location of the second index of the array.
So when you type cout << reverseArray(arr1,6) << endl; you are really just printing out the location of numbers1 in memory. This is why you are getting '0x7fffe697ceb0' in your output. To fix this, simply make your function
void reverseArray(int *numbers1,int length) {
for (int i = length; i >=0; i--) {
cout << numbers1[i] << endl;
}
}
and change your main to:
int main() {
int *arr1 = readNumbers();
reverseArray(arr1,6);
return 0;
}
Now, if you actually want to return this array, you would need to create a new array which holds the reverse numbers and then return that. An example of a function that does that is:
int* reverseArray(int *numbers1,int length) {
int j = 0;
int *numbers2 = new int[length];
for (int i = length-1; i >=0; i--) {
numbers2[j] = numbers1[i];
j++;
}
return numbers2;
}
There are probably better ways to do this, but this is just one solution. Regardless, you should always be careful when allocating memory yourself.

copying static array to dynamic array c++

So I was playing around with some basics in c++ when I noticed this:
int * ptr = new int[3], arr[3] = { 11,13,15 };
for (int i = 0; i < 3; i++)
ptr[i] = arr[i];
cout << ptr[0] << ' ' << ptr[1] << ' ' << ptr[2] << endl;
this code will perfectly insert and print out the values: 11 13 15.
Whereas when I write it this way:
int size=0, * ptr = new int[size], arr[3] = { 11,13,15 };
for (int i = 0; i < 3; i++)
{
ptr = new int[++size];
ptr[i] = arr[i];
}
cout << ptr[0] << ' ' << ptr[1] << ' ' << ptr[2] << endl;
When I increment the size one value at a time, it prints out:
-842150451 -842150451 15
Why is it that when I define the total size at the beginning, the values are properly inserted, however when I increment one step at a time it does not? Also, is there any way to write the second code but in a way where it works please?
As #Ch3esteR points out in the comment. The problem is that you are reallocating your
array on each iteration, and thereby zeroing (or in your case, catching some random
values on the heap).
I would say that the bigger solution might be to use standard containers for handling memory. Here is a solution for fixing your original code original() and a proposed alternative for how to handle dynamic arrays with std::vector.
#include <vector>
#include <iostream>
using namespace std;
void original() {
const int arr[3] = { 11,13,15 };
const int size=3;
auto ptr = new int[size]; // this is what you want to do
std::copy(arr, arr + size, ptr); // Standard function for copying
cout << ptr[0] << ' ' << ptr[1] << ' ' << ptr[2] << endl;
}
int main() {
original();
const int arr[3] = { 11,13,15 }; // You might want to make this a std::vector too
std::vector<int> result{arr, arr + 3};
// std::vector<int> result; // Or if the question was how to do it dynamically
// for (auto i: arr)
// {
// result.push_back(i); // Dynamic add
// }
cout << result[0] << ' ' << result[1] << ' ' << result[2] << endl;
}
On request: How to do it with pointers (don't do this unless you have some external constraint that forces you to do this, like a teacher)
#include <iostream>
using namespace std;
// Reallocate memory and delete the old pointer
int *resize(int *arr, size_t oldSize, size_t newSize) {
auto newArr = new int[newSize];
auto copySize = std::min(oldSize, newSize); // Handle both growing and shrinking resize
std::copy(arr, arr + copySize, newArr); // Copy your old data
// Or do it like this
// for (size_t i = 0; i < copySize, ++i) {
// newArray[i] = arr[i]
// }
delete [] arr;
return newArr;
}
int main() {
auto arr = new int[2] { 11,13 }; // Observe 'new' here
size_t size = 3;
// "resize" the array arr (in practice you are just creating a new one)
arr = resize(arr, size, size + 1);
// Assign your new value
arr[2] = 14;
cout << arr[0] << ' ' << arr[1] << ' ' << arr[2] << endl;
delete [] arr; // Remember, try to not manual memory management,
// only use it in class when you are learning the basics, otherwise use
// std::unique_ptr or std::shared_ptr
}

Fill a char array with int values [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I'm using a library for an Arduino project that has a function I need to call. This function accepts just one parameter of type const char*. Let's call it foo.
I need to pass some int values to foo, so I convert them first using sprintf. So far so good.
The problem comes when I try to fill an array with int values converted to char and then call foo with each of the values in the array.
I hope this explains the problem better:
#include <iostream>
using namespace std;
// This function cannot be modified because
// is a part of a library
void foo(const char *bar){
cout << "Result: " << bar << endl;
}
int main() {
char *values[10]; // My array of values
char tmp[10]; // Temporary buffer for the int > char conversion
for(int i = 0; i < 10; i++){
int samplevalue = i * 2; // Just a sample value, not important
sprintf(tmp, "%d", samplevalue); // Copy the sample value to the temporary buffer
values[i] = tmp; // Assign the value of the temp var to a position in my values array
cout << values[i] << endl;
}
cout << "==============" << endl;
// Here comes the problem:
for(int i = 0; i < 10; i++){
foo(values[i]);
}
return 0;
}
The output of that code is the following:
0
2
4
6
8
10
12
14
16
18
==============
Result: 18
Result: 18
Result: 18
Result: 18
Result: 18
Result: 18
Result: 18
Result: 18
Result: 18
Result: 18
As you can see, all of the Result lines are equal to the last value assigned to the tmp var. I guess it's because each of the values in the values[10] array contains a pointer to the tmp variable instead of its actual value.
What I'd like to have is a different number on each Result line, as in the first for loop.
I guess it's pretty obvious that I'm not even near to be a C++ expert and any help will be highly appreciated.
Thanks!
A char * pointer and an array are not a string. Use std::string instead.
#include <iostream>
using namespace std;
// This function cannot be modified because
// is a part of a library
void foo(const char *bar)
{
cout << "Result: " << bar << endl;
}
int main(void)
{
std::string values[10]; // My array of values
char tmp[10]; // Temporary buffer for the int > char conversion
for (int i = 0; i < 10; i++) {
int samplevalue = i * 2; // Just a sample value, not important
sprintf(tmp, "%d", samplevalue); // Copy the sample value to the temporary buffer
values[i] = tmp; // Assign the value of the temp var to a position in my values array
cout << values[i] << endl;
}
cout << "==============" << endl;
// Here comes the problem:
for (int i = 0; i < 10; i++) {
foo(values[i].c_str());
}
return 0;
}
When using an array, all the pointers in your values array point to tmp, you can check that by looping through values and printing the address like this
fprintf(stdout, "%p\n", values[i]);
So because you sprintf() into tmp all the values, the value that will be printed is always the last one, there is no copy implied in
values[i] = tmp;
that just makes values[i] point to tmp, so when you access values[i] you really access tmp.
With std::string copy occurs.
Also, you should probably use a string stream to write numbers into each values[i] directly, because sprintf() is very dangerous.
Or even better use a real c++ solution like this one,
#include <iostream>
#include <vector>
#include <sstream>
// This function cannot be modified because
// is a part of a library
void foo(const char *bar)
{
std::cout << "Result: " << bar << std::endl;
}
int main(void)
{
std::vector<std::string> values;
for (int i = 0; i < 10; i++) {
values.push_back(std::to_string(2 * i));
std::cout << values[i] << std::endl;
}
std::cout << "==============" << std::endl;
for (size_t i = 0; i < values.size(); i++) {
foo(values[i].c_str());
}
return 0;
}
Note that now, you can change the number of elements in values and you can use it as an array if you need to, just read the documentation for std::vector.
Ok, I finally got to get it working. In Arduino strings are declared as String variable;, and the c_str() function converts a string into a const char *, so I convert the int number to String, and then to const char *:
for(int i = 0; i < 10; i++){
String tmp = String(i * 2);
values[i] = tmp.c_str();
}
And that's it! It works now :)

reserving continuous block using malloc

I'm trying to learn more about malloc() and need help clarifying the output. I want to reserve 10 bytes of memory and be able to access them individually but they must be in one block. Here is the code:
#include<iostream>
using namespace std;
#include<stdio.h>
#include<stdlib.h>
int main()
{
char neededbytes = 10;
char *p;
p = (char *)malloc(neededbytes * sizeof(char));
if(p==NULL)
{
cout<<"Error! memory not allocated.";
exit(0);
}
else
{
for (int i = 0; i < neededbytes; i++)
{
p[i] = 0;
}
for (int i = 0; i < neededbytes; i++)
{
cout<<"Address at index " << i << " is ";
cout<<&p+i<<endl;
}
}
free(p);
}
The output of the program shows that all addresses are 8 bytes apart. Shouldn't they be only one byte apart? Is there a way for me to know if char consumes 8 bytes on my architecture?
&p+i is the same as (&p)+(i), and since p has type char*, &p has type char**. As a result, adding i will actually add i * sizeof(char *) bytes to the address denoted by &p.
What you want is p + i, which will add i * sizeof(char) bytes to the address stored in p. In other words, you already have a pointer to contiguous data when you use malloc(). Of course, this is C++, so char * is handled specially by std::cout, std::cerr, and the std::ostream class in general. You'd need to do something like static_cast<void *>(p + i) rather than just p + i as you would use in C.
As others have stated, you should avoid using malloc() and free() in C++ when possible; C++ has the new[] and delete[] operators for your purpose.
cout<<&p+i<<endl; should just be cout<<static_cast<void*>(p+i)<<endl;
It's because you are using the address of operator, the offset will be i * sizeof(char *) in that case which on your system is apparently 8 * i bytes.
Try this instead
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
char neededbytes = 10;
char *p;
p = static_cast<char *>(malloc(neededbytes));
if (p == NULL)
{
cout << "Error! memory not allocated.";
exit(-1);
}
for (int i = 0; i < neededbytes; i++)
p[i] = 0;
for (int i = 0; i < neededbytes; i++)
{
cout << "Address at index " << i << " is ";
cout << static_cast<void *>(p + i) << endl;
}
free(p);
}
You could look at the byte alignment of char in your compiler output settings but I bet char is always 1 byte. Try a few changes like this (I think you are accessing the wrong array element at &p+i) :
int main()
{
int neededbytes = 10;
char *p=NULL;
p = malloc(neededbytes * sizeof(char));
if(p==NULL)
{
cout<<"Error! memory not allocated.";
exit(0);
}
else
{
for (int i = 0; i < neededbytes; i++)
{
p[i] = 0;
}
for (int i = 0; i < neededbytes; i++)
{
cout<<"Address at index " << i << " is ";
// Dave cout<<p+i<<endl;
cout<<&(p+i)<<endl;
}
}
free(p);
}
NB: Dave shared the correct syntax of p+i. Thanks Dave
Change cout<<&p+i<<endl; to cout<<static_cast<void*>(p+i)<<endl;.
Here's a site that talks about memory alignment on GNU systems. It will always be 8(16 for 64 bit systems) byte aligned. There are some libc (stdlib.h) functions that can force alignment for you listed there though.
http://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html