So I was using malloc in my program and then realloc within a method inside the program. After I called this method so many times I would get a "Segmentation fault (core dumped)".
Upon further inspection I realized that for some reason when my pointer goes from 0x25d7d60 or 0x223fae0 (or any address represented by 7 digits (0xHHHHHHH) ) to 0x7f47d370a010 (with more than 7 digits) for example, a segfault is thrown from within the realloc call, realloc wont even return NULL. I fixed this by simply using malloc and then memcpy instead. However I am very confused at why this happened and wanted to see if any of the users of stackoverflow could shed some light on why this happened.
Thanks
Here is the relevant code:
unsigned int* myArray;
unsigned int num_ints;
int main()
{
num_ints = 100;
if((myArray =(unsigned int*) malloc(sizeof(unsigned int)*(num_ints)*3))==NULL)
{
std::cout << "Malloc failed!" << std::endl;
return false;
}
.
.
.
//This called when n key is pressed (code left out)
methodName();
return true;
}
void methodName()
{
if((myArray =(unsigned int*) realloc(myArray,sizeof(unsigned int)*(num_ints*4)*3))==NULL)
{
std::cout << "Realloc failed!" << std::endl;
exit(0);
}
}
There's a good chance that, by calling "realloc within a method inside the program", you're actually loading it into a local variable which is then thrown away and your program continues to use the older pointer (which has now been freed).
We would need to see the code to be certain but, in my experience, that's the one of the major causes of allocation errors.
Based on what you've shown, there's nothing wrong with what you're doing. It's effectively the same as this code:
#include <iostream>
#include <cstdlib>
int sz = 1000;
int *buffer = 0;
static int methodName (void) {
if (sz == 100000)
sz = 100;
sz = sz * 10;
if ((buffer = (int*)realloc (buffer, sz)) == 0) {
std::cout << "Realloc error" << std::endl;
return 1;
}
return 0;
}
int main(void) {
int i;
if ((buffer = (int*)malloc (sz)) == 0) {
std::cout << "Alloc error" << std::endl;
return 1;
}
for (i = 0; i < 10000000; i++)
if (methodName() != 0)
return 1;
std::cout << "All okay" << std::endl;
return 0;
}
which works perfectly, doing ten million reallocations.
So the problems lies outside what you've shown us, perhaps a compiler bug (pretty unlikely if you're using a mainstream compiler) or memory corruption from elsewhere in your code.
If realloc
changes the address of the array, then the myarr
in the function scope (local) gets the new value, it does not change the myarr
variable in the main
+---------+
| val1 | = malloc (whatever); <--------------------------+
+---------+ |
|myarr | |
+---------+ |
|addr_main| |
+----+----+ |
| |
| |
| (NO EFFECT on here)
(value of the myaddr 'val1') |
(in main passed by value) |
(to function) |
| |
+-------+ |
| |
v |
methodname (myarr, someint) |
| |
| |
V |
+---------+ |
| val1 | = realloc (myarr, whatever) ---------+
+---------+
|myarr | if 'realloc' returns a new address
+---------+ it will only overwrite 'val1' with some 'val2'
|addr_func| in this LOCAL copy with address 'addr_func'
+---------+
|
|
V
(destroyed after function return)
You didn't change myArr in the main scope, realloc maybe return a new address, the old address is invalid.
The problem is that your methodName
function is assigning the new pointer to it's local copy of myArray.
The quick fix is to make myArray a pointer to a pointer like so:
void methodName(unsigned int **myArray, unsigned int num_ints)
{
if((*myArray = (unsigned int *)realloc((*myArray), sizeof(unsigned int)*(num_ints*4)*3)) == NULL)
{
std::cout << "Realloc failed!" << std::endl;
exit(0);
}
}
and then call it by passing the address of myArr:
methodName(&myArr, n_ints);
That way methodName gets the address of the memory of main()
s myArr so that it can write into it.
As you can see though, having function parameters that output values can get a little hairy so I suggest instead return
ing the new address:
unsigned int *methodName(unsigned int *myArray, unsigned int num_ints)
{
return (unsigned int *)realloc(myArray, sizeof(unsigned int) * (num_ints * 4) *3);
}
Then it's just a matter of overwriting myArr
in main
:
myArr = methodName(myArr, n_ints);