I am practicing memory allocation and disk management with C++. I just all of the work.. it just looks and seem's a little too easy. I am not sure if my pointer and my allocation and deallocations are correct. My Total FreeSpace looks like it will work, but it looks too basic. I just need someone's programming experience. When I try to run this code it gives me some kind of Error.
Bug Error
Please DO NOT ADD any new Global Variable.
const int MMSIZE = 60136;
char MM[MMIZE];
//** Initialize set up any data needed to manage the memory
void initializeMemory(void)
{
//**increments through the POOL_SIZE
for (int a = 0; a < MMSIZE; a++) {
MM[a] = 'NULL';
}
}
// return a pointer inside the memory
// If no chunk can accommodate aSize call onOutOfMemory()
void* allocate(int size)
{
//******NOT SURE*******
int *p = new int;
*p = 5;
return ((void*) 0);
}
// Free up a chunk previously allocated
void deallocate(void* mPointer)
{
//******NOT SURE*******
int *p = new int;
delete p;
p = 0;
p = new int(10);
}
//Scan the memory and return the total free space remaining
int remaining(void)
{
//******NOT SURE*******
int free = 0;
for (int a = 0; a < MMSIZE; a++)
{
if (MM[a] < MMSIZE)
{
free += a;
}
}
int free2 = free - MMSIZE;
return free2;
}
This code looks unfinished for even a sample but
//** Initialize set up any data needed to manage the memory
void initializeMemory(void)
{
//**increments through the POOL_SIZE
for (int a = 0; a < MMSIZE; a++) {
MM[a] = 'NULL';// <=== this should not even compile as the single quote should only take one character like '\x0' or 'N'
}
}
should not even compile as the single quote should only take one character like '\x0' or 'N'
but post the complete module and i can help you more and maybe explain a few things.
Without discussing other aspects of your code (such as memory leaking etc), the specific error you are getting most likely comes from *int_pointer = 0xDEADBEEF; line. int_pointer is equal to 0, because int_pointer = (long *)allocate(sizeof(long)); and your void* allocate(int size) with its return ((void*) 0); always returns 0. So you are getting exactly that exception: attempting to write 0xDEADBEEF at address 0x00000000, which is a forbidden operation (there is some OS specific stuff at low addresses).
Related
How can I allocate and deallocate an array of function pointers in C++? I've tried two different strategies, first using single pointers and the second using double pointers but I can't seem to make valgrind happy. Here is my situation:
// function pointer
typedef double(*function_ptr)(double);
// function that adhers to the interface set by function_ptr
double do_nothing(double x) {
return x;
}
// dynamically create array of #param size function pointers, all pointing to do_nothing
function_ptr **make_function_ptr(int size) {
function_ptr xp = &do_nothing_transform;
function_ptr* xpp = &xp;
auto **trsfm = (ESfcnTrsfm **) malloc(sizeof(function_ptr *));
for (int i = 0; i < size; i++) {
trsfm[i] = (ESfcnTrsfm*) malloc(sizeof(function_ptr));
trsfm[i] = xpp; // same as trsfm[i] = ...
}
return trsfm;
}
// free the array of function pointers
void free_function_ptr(function_ptr **fun, int size) {
for (int i=0; i<size; i++){
free(fun[i]);
fun[i] = nullptr;
}
free(fun);
fun = nullptr;
}
Your make_function_ptr function allocates space for only one function_ptr in the 'outer' table, rather than allocating space for size pointers. So, this:
auto **trsfm = (ESfcnTrsfm **) malloc(sizeof(function_ptr *));
Should be:
auto **trsfm = (ESfcnTrsfm **) malloc(sizeof(function_ptr *) * size); // Need to multiply by "size"
Without this, the trsfm[i] access in the subsequent for loop is undefined behaviour, when i is anything other than zero.
Furthermore (as pointed out in the comments), you are allocating memory in that for loop unnecessarily. You need only assign the address of the dummy routine to the allocated table entries:
for (int i = 0; i < size; i++) {
// trsfm[i] = (ESfcnTrsfm*) malloc(sizeof(function_ptr)); // Unnecessary!
trsfm[i] = xpp; // same as trsfm[i] = ...
}
(And, similarly, you don't need the for loop to free those pointers in your free_function_ptr function.)
This line is obviously wrong:
auto **trsfm = (ESfcnTrsfm **) malloc(sizeof(function_ptr *));
You need to allocate that multiplied by "size".
When I run this program sr1, sr2, sr3, sr4 objects are created and values are assigned to corresponding variables. But in sr5 object, the name remains blank while the roll_no percentage shows the correct value.
When change the value of
int MAX = 5;
to
int MAX = 6;
everything works fine.
Here is my code:
const int MAX = 5;
const int FREE = 0;
const int OCCUPIED = 1;
int flag = 0;
using namespace std;
void warning()
{
cout<<"\n------All memory occupied------"<<endl;
exit(1);
}
class student_rec
{
private:
char name[25];
int roll_no;
float percentage;
public:
student_rec(char *n, int r, float per)
{
strcpy(name, n);
roll_no = r;
percentage = per;
}
student_rec()
{
}
void set_rec(char *n, int r, float per)
{
strcpy(name, n);
roll_no = r;
percentage = per;
}
void show_rec()
{
cout<<"\n-------------------\n";
cout<<"Name= "<<name<<endl;
cout<<"Roll number= "<<roll_no<<endl;
cout<<"Percentage= "<<percentage<<endl;
}
void *operator new (size_t sz);
void operator delete (void *d);
};
struct memory_store
{
student_rec obj;
int status;
};
memory_store *m = NULL;
void *student_rec::operator new (size_t sz)
{
int i;
if(flag == 0)
{
m = (memory_store *) malloc(sz * MAX);
if(m == NULL)
warning();
for(i=0; i<MAX; i++)
m[i].status = FREE;
flag = 1;
m[0].status = OCCUPIED;
return &m[0].obj;
}
else
{
for(i=0; i<MAX; i++)
{
if(m[i].status == FREE)
{
m[i].status = OCCUPIED;
return &m[i].obj;
}
}
warning();
}
}
void student_rec::operator delete (void *d)
{
if(d == NULL)
return;
for(int i=0; i<MAX; i++)
{
if(d == &m[i].obj)
{
m[i].status = FREE;
strcpy(m[i].obj.name, "");
m[i].obj.roll_no = 0;
m[i].obj.percentage = 0.0;
}
}
}
int main()
{
student_rec *sr1, *sr2, *sr3, *sr4, *sr5, *sr6, *sr7;
sr1 = new student_rec("sandeep", 21, 78);
sr1->show_rec();
sr2 = new student_rec("sachin", 21, 78);
sr2->show_rec();
sr3 = new student_rec("sapna", 21, 78);
sr3->show_rec();
sr4 = new student_rec("vipin", 21, 78);
sr4->show_rec();
sr5 = new student_rec("niraj", 21, 78);
sr5->show_rec();
sr6 = new student_rec; // error all memory occupied.
return 0;
}
I run this code on linux machine.
This is terrible code. It is totally unaware of the C++ object model. Forget it and start with a good introductory book, that explains the object lifecycle, and how to properly create new objects.
More explanations about what goes wrong: flaw 1
The problem is in student_rec::operator new (). This line:
m = (memory_store *) malloc(sz * MAX);
let you think that m points to some valid array of memory_store objects. Unfortunately, the C malloc() is used to allocate raw memory. There are thus no valid objects in that memory. Otherwise said, the objects pointed to by m are in an unknown dirty state.
Later, the line
m[i].status = FREE;
handles the objects pointed by m as if they were already valid. This is undefined behavior. If you don't allocate objects the C++ way (e.g. new instead of malloc() ) you would first need to create them with a placement new.
Now for your simple object trivial object this will not cause too many damages. There's yet another flaw.
Even more explanations about what goes wrong: fatal flaw 2
There is a second serious problem: malloc only allocates sz * MAX bytes. As the operator is overloaded for student_rec, it will be called with sz being sizeof(student_rec). But your code assumes that it is sizeof(memory_store), so that the allocated memory is at least sizeof(int)*n bytes too short !!
This is why increasing MAX (and thus allocating more memory than needed for your 5 objects) seems to work.
Other remarks
Using global variables as you did, exposing m to the outside world, is very dangerous and error prone. Suppose that in some other functions you'd like to use a local variable m, but forget to declare it; you could corrupt your data structure much faster than you'd expect ! You'd better make it a private static member of student_rec.
Forget about fixed char arrays for storing C strings. If a name would be longer than expected, you'd get another serious problem that is difficult to spot (strcpy could result in memory corruption in such case). If you code in C++, take advantage of string in order not to worry about such details :-)
Stylistic remark: why not make flag a boolean and use true & false instead of 0 and 1 ?
Stylistic remark: The warning() function has a misleading name: warning() suggests that you issue a warning and continue. Why not giving it a self-documenting name like for example fatal_error() or warning_and_exit()
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.
My program has been written using classes from the SDL library.
I have the following class:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** F;
float* F_current;
unsigned int S_total;
unsigned int S_current;
public:
s_group(void);
virtual ~s_group(void);
bool setup( const char* filename, unsigned int s );
//other member functions
};
Private member pointers each store the location of memory declared on the heap, as allocated by the member function setup.
bool s_group::setup( const char* filename, unsigned int s )
{
s_group::~s_group();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
F = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
F[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
Within a large function I create an object of this class on the heap, storing its address in an s_group pointer named sparkle.
s_group* sparkle = new s_group;
sparkle->setup("sparkle_final.png", 1 );
On completion of the function I call delete to reallocate the heap memory. Removing this line solves the problem, however there would then be a memory leak.
delete sparkle;
sparkle = NULL;
This will call the destructor of the class which is where I believe the error occurs due to an internal use of the delete operator.
s_group::~s_group(void)
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
F[s][f].x = 0;
F[s][f].y = 0;
F[s][f].w = 0;
F[s][f].h = 0;
}
delete[] F[s];
F[s] = NULL;
}
delete[] F;
F = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
On reaching the delete operator, a dialog box appears stating:
Windows has triggered a breakpoint in Program.exe. This may be due to a corruption of the heap, which indicates a bug in Program.exe or any of the DLLs it has loaded.
How do I delete this object without causing the heap corruption?
From effective C++ Scott Meyers
Item 9: Never call virtual functions during construction or destruction.
You shouldn't call virtual functions during construction or destruction, because the calls won't do what you think, and if they did, you'd still be unhappy. If you're a recovering Java or C# programmer, pay close attention to this Item, because this is a place where those languages zig, while C++ zags.
Actually, even though you should define your destructor, calling it forcibly should be out of the question
I'm unable to compile your code but here goes..
The first thing I noticed was that you called your destructor.. You don't want to do that! Instead, create a release function and call that.
The next thing I noticed is that there is no FRAME variable within the class itself.. so this line:
FRAME = new SDL_Rect*[S_total];
is going to cause a compilation error and your destructor uses FRAME but no such variable exists. I think you meant to change it to F because if not, then this line:
F[index] = NULL;
is undefined behaviour since F is uninitialized..
Also, you never initialized each index of FRAME and so accessing it in the destructor like:
FRAME[s][f].x = 0;
is a no-no.
Again, you call
delete[] F;
F = NULL;
but F has no memory allocated and is uninitialized.
Thus with all the patches I think:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** FRAME;
float* F_current;
unsigned int S_total;
unsigned int S_current;
void Release();
public:
s_group(void);
virtual ~s_group(void);
bool setup(const char* filename, unsigned int s);
//other member functions
};
bool s_group::setup(const char* filename, unsigned int s)
{
Release();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
FRAME = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
FRAME[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
void s_group::Release()
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
if (FRAME[s])
{
FRAME[s][f].x = 0;
FRAME[s][f].y = 0;
FRAME[s][f].w = 0;
FRAME[s][f].h = 0;
}
}
delete[] FRAME[s];
FRAME[s] = NULL;
}
delete[] FRAME;
FRAME = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
s_group::~s_group(void)
{
Release();
}
should do it.. Just don't forget to allocate memory for FRAME[index] I wasn't sure how much or what you wanted to allocate so I changed the Release function to check if FRAME[index] is valid with an if-statement
I would strongly advise that you use some SmartPointers and forget about handling every single memory allocation yourself..
Since posting this question I have located the source of the error and solved the issue.
In a separate section of code which set the data values for the dynamic 2D array the loop validation was incorrect.
for( unsigned int index = 0; index <= F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
As can be seen the loop will clearly attempt to modify a location equal to the size of the created array. Noting of course that arrays begin at index 0, so the final slot will be at size - 1. Something very silly that I missed when writing the code. Actual loop:
for( unsigned int index = 0; index < F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
A message for anyone attempting their own memory management:
Finding the source of heap corruption is difficult as the compiler will locate the error in sections of code which do not necessarily cause the problem.
The cause of the problem will only ever be in the section of your code which is affecting the memory. Ensure that you do not attempt to access or worse modify any memory that you have not been given.
I still believe that memory management is a great way to learn and would rather complete any projects in this way than using containers or smart pointers as recommended. This is my personal preference despite custom memory management often offering very few advantages, only complexities.
When asking for assistance provide all related code on the problem. Although the compiler may direct you to the problem in one section, as I said before, with heap corruption it's not necessarily there.
void longcatislong(int* cat, int &size, int &looong)
{
int* longcat = new int[looong*2];
for(int i = 0; i < size; i = i + 1)
longcat[i] = cat[i];
delete [] cat;
cat = longcat;
looong = looong * 2;
}
Soup guys. I'm /r/equesting some help with this problem I have with my code. Apparently something in my C++ code caused a heap corruption error and that something is delete[] cat. cat is a dynamic array of ints that was created with the new operator and a pointer. Why, then is it that when I use the array delete the whole program decides to get crushed under a steamroller and say I got heap corruption. I'm 12 and what is this?
You are passing cat pointer by value so whatever changes you do inside the function is not reflected outside. You need to pass the pointer by reference like int*& cat.
cat is not being returned to the caller of this function. You're only changing the local copy when you execute cat = longcat.
That means the parameter that you passed in to this function still points to the old address which you've very inconveniently deleted.
Either pass it in as a reference or do the old C double pointer trick and pass in its address.
You may also want to ensure that the first time you call this, cat has a valid value and that size and looong are compatible (looong * 2 >= size) lest you corrupt memory.
Have a look at the following code which illustrates your problem:
#include <iostream>
void longcatislong1(int* cat, int &size, int &looong)
{
int* longcat = new int[looong*2];
for(int i = 0; i < size; i = i + 1)
longcat[i] = cat[i];
delete [] cat;
cat = longcat;
looong = looong * 2;
}
void longcatislong2(int*& cat, int &size, int &looong)
{
int* longcat = new int[looong*2];
for(int i = 0; i < size; i = i + 1)
longcat[i] = cat[i];
delete [] cat;
cat = longcat;
looong = looong * 2;
}
int main (void) {
int sz = 0;
int lng = 10;
int *ct = 0;
std::cout << ct << std::endl;
longcatislong1 (ct, sz, lng);
std::cout << ct << std::endl;
longcatislong2 (ct, sz, lng);
std::cout << ct << std::endl;
return 0;
}
Its output is:
0
0
0x9c83060
meaning that the longcatislong1 call did not successfully set ct on return. The longcatislong2 function, which passes the pointer in as a reference, does set ct correctly.
So let's say you have a valid pointer to 0xf0000000. When you call your original function, a new memory block is allocated, the data is copied across and the old block is deleted.
But the ct variable still points to the old block.
The next time you call the function, or even if you dereference ct elsewhere, you're in for a world of pain, commonly called undefined behaviour.
By making the first parameter a reference type, changes made in the function are reflected back in the variable that was passed in.
You should remove int* cat by int** cat in function args, and then replace all cat insertions
in function body by *cat even in cat[i] placement.
void longcatislong(int** cat, int &size, int &looong)
{
int* longcat = new int[looong*2];
for(int i = 0; i < size; i = i + 1)
longcat[i] = *cat[i];
delete [] *cat;
*cat = longcat;
looong = looong * 2;
}
And then when you call function call it like that:
longcatislong(&cat, size, looong);