I have the following variables defined locally in a function member of a class in C++:
double coeff, mincoeff, minratio,
equality[100][5000],
tableau[51][5052],
x[50][100];
When running the program crashes. When I comment out equality array it works but If I do not comment it out, it make the program crashes. It is not true for tableau array and it always works with 'tableau' array and without 'equality' array. I saw a post to use malloc() function to assign space dynamically like :
double *equality;
equality = malloc(500000*sizeof(double));
But it gives me an error of no conversion from void* to double*. Is there another way?
allocate eqaulity on the heap and when you're done with it free memory:
int main()
{
double** equality = new double* [100];
for(int i(0); i < 100; i++)
equality[i] = new double[5000];
for(int i = 0; i < 100; i++)
delete[] equality[i];
delete[] equality;
equality = NULL;
std::cout << std::endl;
return 0;
}
Like #user657267 have mentioned, you are asking 4MB of continuous chunk of memory for equality. Best thing to do here is to ask for the memory dynamically.
double **equality = new (nothrow) double*[100]; //Or do exception check to make sure you have enough memory
if (equality!=nullptr)
{
for(int i(0); i < 100; i++)
{
equality[i] = new (nothrow) double[5000]; //Again or do exception check to handle exception if it cannot get asked memory.
if (equality[i] == nullptr)
{
//Handle the situation where memory could not be allocated
...
}
}
}
else
{
//Handle not being able to allocate memory
}
Regarding c-style malloc (works with C++ as well), you have to cast to correct data type like following:
double *equality;
equality = (double*) malloc(500000*sizeof(double));
Note: do not forget to free what you have allocated.
Related
I am trying to recreate the vector class and I believe there is a memory leak in my code, but I don't know how to solve it. Using the CRT Library in my Visual Studio, it tells me that there is a supposed memory leak that doubles for each time that reserve is called.
I am not quite sure why that is or if there even is a memory leak. The memory leak detection says that it is this line in the reserve function int* temp = new int[n];
This is what I understand to be happening in the reserve function:
Once the contents of arr are copied into temp, it's fine to delete arr. Assigning arr = temp should work because all I'm doing is making arr point to the same place as temp. Because arr was previously deleted, I only have 1 array in the heap and arr and temp both point to the same array so there should be no memory leak. Temp shouldn't matter because it disappears after it exits the scope. On subsequent calls to the reserve function, every thing repeats and there should only be one array in the heap which arr points to.
I do believe that my thinking is probably erroneous in some way.
#include "Vector.h"
namespace Vector {
vector::vector() {
sz = 0;
space = 0;
arr = nullptr;
}
vector::vector(int n) {
sz = n;
space = n;
arr = new int[n];
for(int i = 0; i < n; i++) {
arr[i] = 0;
}
}
void vector::push_back(int x) {
if(sz == 0) {
reserve(1);
} else if (sz == space) {
reserve(2*space);
}
arr[sz] = x;
sz++;
}
void vector::reserve(int n) {
if (n == 1) {
arr = new int[1]; //arr was a nullptr beforehand
}
int* temp = new int[n];
for(int i = 0; i < n; i++) {
temp[i] = arr[i];
}
delete[] arr;
arr = temp;
space = n;
}
Your code assumes in vector::reserve(int n) that arr is null.
Instead maybe spilt up how reserve functions based on whether or not arr is null.
void vector::reserve(int n) {
if (arr) { //handle case when arr is null
space += n;
arr = new int[space];
//no need to copy anything!
} else { //handle case when arr is not null
int* tmp(new int[space + n]);
for(int i = 0; i < space; i++) {
tmp[i] = arr[i];
}
delete[] arr;
arr = tmp;
space += n;
}
}
Also the above code assumes you mean to reserve space+n instead of allowing reserve to shrink the array as you'll lose data if you reserve less then a previous reserve. It's usually better practice to not use assumptions about a pointer's state when working with them because when your code gets more complex the assumptions can end up getting forgotten or more obscure.
I have same issues too. I have created two pointers that points in the same address in heap. When I'm trying too deallocate the memory, and the result is only one pointer that can do that, it's the first pointers that point that address. The second or third pointers that points that address doesn't have an authority to deallocate the memory, but only the first pointers who have that authority.
Example
int *a = new int[5];
int *b = a;
int *c = a;
Pointers b and c doesn't have an authority too dealloacte the memory address that pointers a pointed. Therefore, the memory wasn't deallocated if i'm saying delete[] b nor delete[] c, they didn't have an authority for doing that. Then I tried to write delete [] a and that worked. I don't have an real answers, and I just trying to approaching through my try and errors that I have done. And that's what I got.
Actually this case is violating the rules, but C++ still allowed us to do it, it's called undefined behaviors. We are violating the rules of delete[] operators by, but C++ still allowed you to do, and as the result, you get unexpected output.
Not too much wrong in there.
Bugs
if (n == 1) {
arr = new int[1]; //arr was a nullptr beforehand
}
The comment cannot be guaranteed. Nothing prevents multiple calls of resize including a call of reserve(1), and that will leak whatever memory was pointed at by arr. Instead consider
if (arr == nullptr) {
arr = new int[n]; //arr was a nullptr beforehand
}
now the comment is guaranteed to be true.
The copy loop overshoots the end of arr every time the size of the array is increased.
for(int i = 0; i < n; i++) {
temp[i] = arr[i];
}
arr is only good up to arr[sz-1]. If n is greater than space, and it almost always will be, arr[i] wanders into the great wilds of Undefined Behaviour. Not a good place to go.
for(int i = 0; i < n && i < sz; i++) {
temp[i] = arr[i];
}
Checks both n and sz to prevent overrun on either end and copying of data that has not been set yet. If there is nothing to be copied, all done.
Targets of opportunity
The class needs a destructor to release any memory that it owns (What is ownership of resources or pointers?) when it is destroyed. Without it, you have a leak.
vector::~vector() {
delete[] arr;
}
And if it has a destructor, the Rule of Three requires it to have special support functions to handle (at least) copying of the class or expressly forbid copying.
// exchanges one vector for the other. Generally useful, but also makes moves
// and assignments easy
void vector::swap(vector& a, vector& b)
{
std::swap(a.sz, b.sz);
std::swap(a.space, b.space);
std::swap(a.arr, b.arr);
}
// Copy constructor
vector::vector(const vector& src):
sz(src.sz),
space (src.space),
arr(new int[space])
{
for(int i = 0; i < sz; i++) {
arr[i] = src.arr[i];
}
}
// move constructor
vector::vector(vector&& src): vector()
{
swap(*this, src);
}
// assignment operator
vector::vector& vector::operator=(vector src)
{
swap(*this, src);
return *this;
}
The Copy Constructor uses a Member Initializer List. That's the funny : bit.
The assignment operator makes use of the Copy and Swap Idiom. This isn't the fastest way to implement the assignment operator, but it is probably the easiest. Start with easy and only go to hard if easiest doesn't meet the requirements.
I tried to write code where i have to return the pointer pointing to the first element of array.
I tried using this:-
int *construct(int arr[],int n)
{
int size=(int)(ceil(log2(n)));
size=2*pow(2,size)-1;
int st[size];
for(int i=0;i<size;i++)
st[i]=INT_MAX;
constructUtil(arr,st,0,n-1,0);
int *pt=&st[0];
return pt;
}
This gave me error.
But when i declared the same array like this:
int *st=new int[size];
It executed successfully.
What is the difference between these two?
You canĀ“t return a pointer to a local array in C. You have to use malloc to allocate the memory and generate a pointer to a memory region for your array. Now you can return the pointer and the memory stays valid:
#include <stdio.h>
#include <stdlib.h>
int* construct(int n);
int main()
{
int* ArrayPointer = construct(100);
printf("Address: %p", ArrayPointer);
for(int i = 0; i < 100; i++)
{
printf("%i\n\r", ArrayPointer[i]);
}
free(ArrayPointer);
return 0;
}
int* construct(int n)
{
int* array = (int*)malloc(n * sizeof(int));
for(int i = 0; i < n; i++)
{
array[i] = i;
}
return array;
}
The instruction new does something similar to the malloc function (not exactly the same). The key operation of new is to ask the OS for some free memory for dynamic allocation (like malloc but from another memory pool). See the difference between malloc and new here. Another option (without dynamic memory) is to declare a static array with a fixed size. So the compiler will reserve the memory and you can pass the address of this array to your function
I'm new to C programming.
I want to make a linked list, so I did, but it doesn't work.
After I do that, I made it for a test, but still it gives an error.
malloc: error for object 0xa000000000000000: pointer being realloc'd was not allocated
set a breakpoint in malloc_error_break to debug
How can I reallocate this array?
void Allocate(int **arr,int totalNum, int subNum)
{
for(int n=0;n<(totalNum+1);n++)
{
arr[n] = (int*)realloc(arr[n],(size_t)((subNum+1)*sizeof(int)));
}
}
int main()
{
int totalNum = 20;
int subNum = 5;
int **arr;
arr = (int**)malloc((totalNum+1)*sizeof(int*));
Allocate(arr,totalNum, subNum);
for(int n=1;n<(totalNum+1);n++)
{
for(int s=1;s<(subNum+1);s++)
{
arr[n][s] = rand()%5;
cout<<"arr["<<n<<"]["<<s<<"]: "<<arr[n][s]<<endl;
}
}
}
The program crashes because arr[n] is uninitialized when realloc() is invoked.
i do not fully understand why you want to realloc() instead of malloc() in the Allocate() function. but anyway, let's assume realloc() is what you need.
the easiest fix is to initialize arr content.
arr = (int**)calloc((totalNum+1),sizeof(int*));
The first argument to realloc() has to be either NULL or a pointer that was returned earlier by malloc() or realloc(). You passed an array full of uninitialized data to Allocate(), so you're passing uninitialized pointers to realloc() there. You need to initialize them all to NULL first.
arr = malloc((totalNum+1)*sizeof(int*));
for (int i = 0; i < totalNum+1; i++) {
arr[i] = NULL;
}
Allocate(arr,totalNum, subNum);
This is a follow up from my question at: Array of strings with malloc on C++
As I have implemented Tony D solution, I have allocated memory for an array of std::string with malloc and then created the std:string for each one of the elements with new according to:
void* TP = malloc(sizeof (string) * SS);
for (int i = 0; i < SS; i++) {
new (&((string*)TP)[i]) std::string(Token[i]);
}
(Token is a vector<string> and SS an int)
I know this is not recommended, I know it is not elegant, I know there
are many other solutions for this array creation and filling, but I need to do
it this way
The issue I encounter now is at the array deletion. As I create each std::string separately but the allocation for the array with a malloc, in my destructor I have written:
for (int i = 0; i < SS; i++) {
delete (&((string*) TP)[i]);
}
free(TP);
But when running, the free(TP) is accusing a "double free or corruption".
By commenting the free(TP) I solve the issue for runtime (hidding the real issue), but I need to be sure all memory is released as this may cause a memory leak within the class.
So, is the deletion of each element of TP enough to free all that memory? From my understanding the malloc has allocated memory independently and it needs to be free independently from the std::string elements; but then, why do I get this error?
You're doing a placement-new to run std::string's constructor on the malloc allocated block, but then you're using delete which will run the destructor AND try to free the memory (you don't want to do the second one here since you're freeing with free()).
You want to run the destructor manually, like this...
for (int i = 0; i < SS; i++) {
(&((string*) TP)[i])->~string();
}
free(TP);
First, let's clean up your code. I suggest you stay away from void* for your array type. Then you can do this, which is a little easier to read, especially on the new() operator:
std::string* TP = (std::string*) malloc(sizeof (std::string) * SS);
for (int i = 0; i < SS; i++) {
new (&TP[i]) std::string(Token[i]);
}
Now, to free the strings, you have to call their destructor directly, don't use delete (there is no placement-delete operator, like you are assuming):
for (int i = 0; i < SS; i++) {
TP[i].~string();
}
free(TP);
Now, with that said, you clearly have access to std::vector, so there is no good reason to use malloc() instead:
std::vector<std::string> TP(SS);
for (int i = 0; i < SS; i++) {
TP[i] = Token[i];
}
Or:
std::vector<std::string> TP;
TP.reserve(SS);
for (int i = 0; i < SS; i++) {
TP.push_back(Token[i]);
}
Or:
std::vector<std::string> TP(Token.begin(), Token.begin()+SS);
I have some pointers that I allocate in the constructor of a class and then attempt to delete in its destructor:
TileMap::TileMap(int x, int y) {
mapSize.x = x;
mapSize.y = y;
p_p_map = new Tile*[x];
for(int i = 0; i < x; i++) {
p_p_map[i] = new Tile[y];
}
randomize();
}
TileMap::~TileMap() {
for(int i = 0; i < mapSize.x; i++) {
delete p_p_map[i];
}
delete p_p_map;
}
void TileMap::randomize() {
for(int i = 0; i < mapSize.x; i++) {
for(int j = 0; j < mapSize.y; j++) {
p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());
}
}
}
At the end of the program the destructor is called to free the memory of the pointers I allocated, but when it reaches "delete p_p_map[i];" in the destructor, XCode informs me that the pointer was not allocated. I am new to C++, but I feel that I pretty explicitly allocated memory to the pointers in the randomize() function.
What error am I making?
You have to match delete with new and delete[] with new[]. Mixing one up with the other leads to issues. So if you do:
p_p_map = new Tile*[x];
you have to delete it like:
delete[] p_p_map;
and same with
delete[] p_p_map[i];
If you create something like:
pSomething = new Type;
then you delete it like:
delete pSomething;
What error am I making?
A few:
First, as #uesp pointed out, you mismatch new and delete calls
Second, you are using the "memory leak operator":
p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());
The construct new Tile(...) allocates memory. Then, this memory (not stored anywhere) is dereferenced, and the result is assigned to p_p_map[i][j].
Because the pointer is not stored anywhere, it is leaked.
Third, you are not respecting RAII. While this is not technically an error in itself, the way you write the code is unsafe, and in low memory conditions, you will get UB.
For example, here's what happens if you construct a Tile instance with large values for x and y:
TileMap::TileMap(int x, int y) { // e.g. (x = 1024 * 1024, y = 1024 * 1024 * 1024)
mapSize.x = x;
mapSize.y = y;
p_p_map = new Tile*[x]; // allocate 1049600 pointers block
for(int i = 0; i < x; i++) {
p_p_map[i] = new Tile[y]; // run out of memory (for example) half way through the loop
}
randomize();
}
Depending where your allocations fail, your constructor will not finish executing, meaning your TileMap instance is "half-constructed" (i.e. in an invalid state) and the destructor will not be called.
In this case, everything the class allocated is leaked, and (especially if you allocated a large size) your application is left in low memory conditions.
To fix this, make sure each pointer is managed by a different instance of a class (part of RAII). This ensures that if an allocation fails, the allocated resources are released before exitting the scope, as part of stack unwinding (as #CaptainObvlious said, use std::vector for the array and std::unique_ptr for each element).