realloc pointer change when out of function - c++

i am starting homework about dynamic array, first, I have a 2 dimensional array :
int initializeInfo[3][4] ={{77,68,0,0},{96,87,89,78},{70,90,86,0}};
and use pointer to store it:
int **ptr = (int**)malloc(3*sizeof(int));
int size = 0;
for(int i =0;i<3;i++){
addInitiazeInfo(ptr,initializeInfo[i],size);
}
here is function addInitiazeInfo:
void addInitiazeInfo(int**& ptr, int arr[],int& size){
ptr[size] = (int*)malloc(4*sizeof(int));
if(ptr[size] == NULL){
return;
}
ptr[size] = arr;
size++;
}
It's run OK! The 2 dimensional array is store by ptr pointer.
And I want to add new row, I think realloc is needed, then I try:
int arr[] = {3,4,5,6};
size++;
ptr = (int**)realloc(ptr,size * sizeof( int ) );
ptr[size-1] = (int*)malloc(4*sizeof(int));
ptr[size-1] = arr;
But I think this is my trouble, the output make me hard to know how it happend:
please help me, thanks everyone

When you do
ptr[size] = arr;
You are essentially assigning the address of arr, to ptr[size]. This means that the memory you just allocated is lost and successfully leaked.
You want to manually copy element by element or use something like memcpy. It is likely this might fix your issue, depending on the rest of your code.

Related

Is it safe to delete a void* byte by byte?

Because i don't know verry much about memory allocation, I would like to know if it safe to delete a block of consecutive bytes (array) like this.
void Free(void* ptr, size_t cbSize)
{
if (cbSize == 0) return;
if (ptr == NULL) return;
for(size_t i = cbSize; i > 0; i--)
{
char* p = &((char*)ptr)[i];
delete p;
}
char* p = (char*) (ptr);
delete p;
}
I have tried this method in the following circumstances and got no error.
int* a = new int[100];
Free(a, 100 * sizeof(int));
int* a = (int*) malloc(100 * sizeof(int));
Free(a, 100 * sizeof(int));
You always delete what you allocate; exactly and only what you allocate. If you new a single thing, you delete a single thing. The fact that the "single thing" happens to take up more than one byte is irrelevant; you delete what you new.
How can i make my function work in this case ?
You don't. You newed an array of ints. So you must delete an array of ints. Types matter in C++.

Clear out the STL list of pointers in C++

I have defined a list of pointers. How should I free all these pointers before clearing the list? What is the best approach to erase all list members? In below program, is it required to free memory allocated for struct?? See my inline comments.
struct MyStruct {
char *data;
int len;
};
typedef std::list<struct MyStruct *> myStruct_list;
myStruct_list l_list;
/* Prepare a list */
for( int i = 0; i < 10; i++) {
struct MyStruct *s = (MyStruct *)malloc(sizeof(struct MyStruct));
s->data = (char*)malloc(MAX_LEN);
get_random_data(s->data,size);
s->len = strlen(s->data);
l_list.push_back(s);
}
/* Delete all members from a list */
myStruct_list::iterator it;
for (it = l_list.begin(); it != l_list.end(); ++it) {
if (*it) {
free(*it); // --->> do I need to free (*it)->data ?????
}
}
l_list.clear();
I want to understand is there any memory leak in below program?
Yes you have it right here:
p = (char*)malloc(MAX_LEN);
p = (char *)buf;
you allocate memory and assign it to p and next line you loose it. So:
You should not use malloc() in C++ programs unless you need to pass data that would be managed by C code
You should use special data structure like std::string etc to manage your data.
If you still need to allocate dynamic memory use smart pointers.
How should I debug if there is any memory leak?
You would not create them in the first place. For example, how could you write get_random_str (assuming you really have to allocate it using malloc):
using spchar = std::unique_ptr<char[], decltype(std::free) *>;
spchar get_random_str( int len )
{
spchar s( static_cast<char *>( malloc( len + 1 ) ), std::free );
static const char alphanum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < len; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[len] = '\0';
return s;
}
Note, I did not compile this code, it's to show you the idea.
Update: looks like you think that this code:
p = (char *)buf;
would copy string from buf to p, which is not the case. Instead you make p point to memory of buf loosing old value that malloc() returned before (hence creating memory leak) and you assign that adress of buf to data which leads to UB when you call free() on it, so what you need instead:
strncpy( p, buf, MAX_LEN );
but even that is not necessary as you do not really need buf at all:
void myClass::fillData(void)
{
s = (MyStruct *)malloc(sizeof(struct MyStruct));
s->data = (char*)malloc(MAX_LEN);
get_random_str(s->data,950);
s->len = strlen(s->data);
l_list.push_back(s);
}
but this is more C code, using some C++ syntax. You should get newer compiler and textbook if you really want to learn C++.
Delete elements using lambda function in for_each:
std::for_each(l_list.begin(), l_list.end(), [](const MyStruct* elem){if(elem) free(elem)});
And clear pointers:
l_list.clear();

C++ Where is the seg fault?

I am currently tackling this assignment for my computer science class:
Make your own dynamic array template. It should allow creating contiguous arrays (filled with things of the same type) which you can extend without worrying about running out of space.
Do one version using malloc and free.
Do one version using new and delete.
My version using new and delete works flawlessly; however, in trying to convert my new/delete code to using malloc/free, I keep getting a seg fault. I have narrowed down the segfault (I think), to being in a single function: addData. Take a look at the code in my main I used to test this:
Array2<int> *testArray3 = new Array2<int>(5);
Array2<int> *testArray4;
testArray3->initArray();
testArray3->printArray();
testArray4 = testArray3->addData(7);
testArray4->printArray();
return 0;
This gives a seg fault; however, when I change it to this:
Array2<int> *testArray3 = new Array2<int>(5);
Array2<int> *testArray4;
testArray3->initArray();
testArray3->printArray();
testArray4 = testArray3; //->addData(7);
testArray4->printArray();
return 0;
There is no seg fault. This makes me believe the issue is in my addData function. Here is the code for that:
Array2<T> *addData(T dataToAdd){
Array2 <T> *tmp;
tmp->data = this->getData();
Array2 <T> *newData;
newData->data = (T *) malloc(sizeof(T)*(this->size + 1));
for (int i = 0; i < tmp->getSize() + 1; ++i){
if (i < tmp->getSize()){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}
free(tmp->data);
free(this->data);
return newData;
};
I am new to programming as a whole and have not completely wrapped my head around pointers and memory allocation, etc. Any advice you could give me would be greatly appreciated! In case you need to see the rest of the code, here is the entire file I coded my template in. Thank you so much for your time!
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
using namespace std;
template<typename T>
class Array2{
public:
Array2(int size){
this->size = size;
data = (T *) malloc(sizeof(T)*size);
};
Array2<T> *addData(T dataToAdd){
Array2 <T> *tmp;
tmp->data = this->getData();
Array2 <T> *newData;
newData->data = (T *) malloc(sizeof(T)*(this->size + 1));
for (int i = 0; i < tmp->getSize() + 1; ++i){
if (i < tmp->getSize()){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}
free(tmp->data);
free(this->data);
return newData;
};
~Array2(){
free(this->data);
};
void initArray(){
for (int i = 0; i < this->size; ++i){
//this->data[i] = i;
this->setData(i, i);
}
};
void printArray(){
//ostringstream oss;
string answer = "";
for (int i = 0; i < this->size; ++i){
//oss << this->data[i] + " ";
cout << this->data[i] << " ";
}
//answer = oss.str();
cout << answer << endl;
};
T* getData(){
return this->data;
}
int getSize(){
return this->size;
}
void setData(T data, int index){
this->getData()[index] = data;
}
private:
int size;
T* data;
};
Array2 <T> *tmp;
Allocates a pointer. This does not point the pointer at anything or allocate any storage for the pointer to point at. What it points at without being explicitly assigned is undefined. If you are lucky, and you are this time, tmp points at an invalid location and the program crashes. If you are unlucky, tmp points at some usable region of program memory and lets you write over it, destroying whatever information was there.
tmp->data = this->getData();
Attempts to access the data member at tmp, but fortunately for you the access is in invalid memory and the program comes to a halt. It also has tmp's data pointing at this's data, and that's a dangerous position to be in. Changes to one will happen to the other because they both use the same storage. Also think about what will happen to this->data if you free tmp->data.
Or perhaps I'm wrong and the halt is here for the same reason:
Array2 <T> *newData;
newData->data = (T *) malloc(sizeof(T)*(this->size + 1));
Both need to be fixed. tmp doesn't have to live long, so we can make it a temporary local variable.
Array2 <T> tmp;
Typically this will be created on the stack and destroyed when the function ends and tmp goes out of scope.
But this will not work because Array2's constructor requires a size so it can allocate the array's storage. You need to find out how big to make it. Probably something along the lines of:
Array2 <T> tmp(this->size + 1);
But frankly I don't think you need tmp at all. You should be able to copy the dataToAdd directly into newData without using tmp as an intermediary.
newData is eventually going to be returned to the caller, so it needs a longer scope. Time to use new.
Array2 <T> *newData = new Array2 <T>(this->size + 1);
And through the magic of the constructor... Wait a sec. Can't use new. That makes this hard. malloc doesn't call constructors, so while malloc will allocate resources for newData, it doesn't do the grunt work to set newData up properly. Rule of thumb is Never malloc An Object. There will be exceptions I'm sure, but you shouldn't be asked for this. I recommend using new here and politely telling the instructor they are on crack if they complain.
Anyway, new Array2 <T>(this->size + 1) will allocate the data storage for you with it's constructor.
There is an easier way to do this next bit
for (int i = 0; i < tmp->getSize() + 1; ++i){
if (i < tmp->getSize()){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}
Try:
for (int i = 0; i < tmp->size; ++i){
newData->data[i] = tmp->data[i]; // you were right here
}
newData->data[tmp->size] = dataToAdd;
And back to something I hinted at earlier:
free(tmp->data);
free(this->data);
Both tmp->data and this->data point to the same memory. To be honest I'm not sure what happens if you free the same memory twice, but I doubt it's good. Regardless, I don't think you want to free it. That would leave this in a broken state.
Recap and fixes
Array2<T> *addData(T dataToAdd)
{
Array2 <T> *newData = new Array2 <T>(this->size + 1);
for (int i = 0; i < this->size; ++i)
{
newData->data[i] = this->data[i];
}
newData->data[this->size] = dataToAdd;
return newData;
};
This version leaves this intact and returns a newData that is one bigger than this. What it doesn't do is add anything to this. Which is goofy for a method named addData.
It also leads to stuff like this:
mydata = myData->addData(data);
which leaks memory. The original mydata is lost without deletion, resulting in a memory leak.
What I think you really need is a lot simpler:
Array2<T> & addData(T dataToAdd)
{
this->data = realloc(this->data, this->size + 1);
this->data[this->size] = dataToAdd;
this->size++;
return *this;
};
realloc effectively allocates a new buffer, copies the old buffer into the new one, and frees the old buffer all in one fell swoop. Groovy.
We then add the new element and increment the count of elements stored.
Finally we return a reference to the object so it can be used in a chain.
Usage can be
myData.addData(data);
myData.addData(data).addData(moredata);
myData.addData(data).printArray();
and if you have operator << support written
std::cout << myData.addData(data) << std::endl;
I'd go back over the new version of Array if I were you. Most of the bugs picked off here are conceptual errors and also apply to it. You might just be getting unlucky and it merely looks like it works. I just read C++ Calling Template Function Error. The posted solutions fixed the immediate problem, but did not touch the underlying memory management problems.
As for the rest of your class, I advice following the link and answering What is The Rule of Three? Because Array2 violates the heck out of it.

Segmentation fault - new and delete have been used. Lots of arrays are being created during runtime (unbounded array)

I'm trying to implement an unbounded array: What is an unbounded array?
More details on this page:
http://www.cs.cmu.edu/~fp/courses/15122-s11/lectures/12-ubarrays.pdf
This is the code:
#include <iostream>
#include <cstdlib>
using namespace std;
class UBArray
{
public:
int *arr, *arrN, j, *pos; //Initial array is arr. The position of arr is stored in pos. arrN is the new array created when size = limit.
int size, limit; //size is the current size of the array and limit is the total size available untill a new array is created.
UBArray()
{
size = 0;
limit = 10;
arr = new int[10];
pos = arr;
}
private:
void increment()
{
// New array arrN is created and then the values in the old arrays is put into the new array.
// Limit is increased by 10 - this is the extra space the new array contributres.
// pos which carries the address of the current array now carries the address of the new array.
// Later when a new array is created its address will be on the heap which is empty. This address is replace the address stored
// in the arrN. The older array can still be accessed for the array updation process by using the variable pos.
// IMPORTANT: I had initially tried to delete the older array to space space but while trying to debug the segmentation fault, I have
// removed it. I will be adding it again once the error has been fixed.
arrN = new int[size + 10];
for (j = 0; j < size; j++)
{
arrN[j] = pos[j];
}
limit = limit + 10;
pos = arrN;
}
public:
void push(int n)
{
if (size<limit)
{
size++;
pos[size-1]=n;
}
else
{
increment();
push(n);
}
}
int pop()
{
int p = pos[size-1];
size--;
return p;
}
};
int main()
{
UBArray array;
int num;
cout << "Enter 36 elements: ";
for (int k = 0; k<36; k++)
{
cin >> num;
array.push(num);
}
cout << endl << "The last element is : " << array.pop();
}
I have tried to give comments in the code to make it understandable to the reader. I'm copying some of it here:
Initial array is arr. The position of arr is stored in pos. arrN is the new array created when size = limit.
size is the current size of the array and limit is the total size available until a new array is created.
New array arrN is created and then the values in the old array are put into the new array.
Limit is increased by 10 - this is the extra space the new array contributres.
pos which carries the address of the current array now carries the address of the new array.
Later when a new array is created its address will be on the heap which is empty. This address is replaced the address of arrN. The older array can still be accessed for the array updation process by using the variable pos which will be updated by the old values have been copied to the new one.
I get segmentation fault during execution. I have tried to use cout statements to debug the code but it seems really confusing. I could see loops both inside and outside the for loop inside the increment method. I'm unable to figure out much. Any help is appreciated.
UPDATE: As pointed out by jrok, I changed the code and the seg fault is gone. But I'm getting seg fault again at the creation of the 3rd array.
UPDATE 2 Everything fixed now. Thank you.
arr = new int(10*sizeof(int));
That creates a single int, initialized to the value of 10*sizeof(int). The loop you wrote right after this statement runs out of bounds and it's cause of segmentation fault.
What you want is the array form of new:
arr = new int[10]; // note 10 only, new expression knows the size
// of the type it allocates
Note that when you assign the pointer to the new array to the pointer to the old array you lose the handle to it and create a memory leak:
int* arr = new int[10];
int* new_arr = new int[20];
arr = new_arr; // original array at arr has leaked
You need to delete[] arr before you reassign it. Also, I see no use for the third (pos) pointer. Not even for arrN, for that matter. One will do. Create a local pointer inside increment and assign it to arr when you're done deallocating the old array.
Finally, what people have been telling you in the comments, unless this is a learning exercise, don't try to reinvent the wheel and use std::vector instead.
An unbounded array only needs 3 data members (rather than 6): the address of the beginning of the data buffer, the capacity of the buffer, and the actual size (of the part of the buffer used so far). When expanding, you will temporarily need to hold the address of the new buffer in an automatic variable. Also, you should avoid leaking the memory of previous buffers. A simple layout is like this:
struct ua
{
int size,capacity,*buff; // 3 data members only
ua(int n) // constructor: n = initial capacity
: size(0) // initially empty
, capacity(n<0?0:n) // guard against n<0
, buff(capacity?new int[capacity]:0) {} // only allocate if n>0
~ua() { delete[] buff; } // destructor: note: delete[] 0 is ok
void empty() const { return size==0; } // is array empty?
void push(int x) // add another datum at back
{
if(size==capacity) { // buffer is full: we must expand
if(capacity) capacity+=capacity; // double capacity
else capacity=1; // but ensure capacity>0
int*nbuff=new int[capacity]; // obtain new buffer
if(size)
memcpy(nbuff,buff,size*sizeof(int)); // copy data from old to new buffer
delete[] buff; // free memory form old buffer
buff=nbuff; // set member buff to new buffer
}
buff[size++]=x; // write; increment size (post-fix)
}
int pop() // ill-defined if empty()
{ return buff[--size]; } // read; decrement size (pre-fix)
int operator[](int i) const // ill-defined if i<0 or i>=size
{ return buff[i]; }
int&operator[](int i) // ill-defined if i<0 or i>=size
{ return buff[i]; }
// you may add more functionality, for example:
void shrink(); // reduces capacity to size
void reserve(int n); // extends capacity to n, keeping data
ua(ua const&other); // copy buffered data of other
void swap(ua&other); // swap contents with other (no copying!)
};

glibc detected memory curruption

I have to work and create often matrices(I have to use pointers) so I made a function in C++ to allocate space for them and also make sure that the last value is set to NULL.
The application drops this error(glibc detected: memory curruption) in a specific case. Here is the code:
template<typename T> T *allocate(int size) {
T *temp = new T[size];
temp[size] = (T) NULL;
return temp;
}
This works:
unsigned char *tmp = allocate <unsigned char> (10);
But this one drops the error:
unsigned char **tmp = allocate <unsigned char *> (10);
That would be the equivalent of:
unsigned char **tmp = new unsigned char *[10];
tmp[10] = (unsigned char *) NULL;
Which is good. Why would it drop me this error?
Update: Thanks for the responses. I am so blind. That's one bug. But the problem of the crash was from another part of the code but also because I was adding NULL outside the allocated space of the array.
You can't do this:
temp[size] = (T) NULL;
Size in this case is indexing the memory position AFTER the last one you allocated, change it for this:
temp[size-1] = (T) NULL;
temp[size] = (T) NULL;
is assigning to unallocated memory.
T *temp = new T[size];
allocates from temp[0] to temp[size-1]