I have a map where the key value is the address of a 2 dimensional pointer and value is some metadata about image.
When I run valgrind on allocate and release functions, valgrind shows invalid read of 4 error.
struct MemType
{
// Store the data type of the pointer
int dataType;
int noOfRows;
int noOfColumns;
int noOfItems;
};
map < unsigned long, MemType > _MemHandle2DPointer;
short** AllocateMemory(int rowSize, int columnSize)
{
short** ptr2D = new short*[rowSize];
for (unsigned int i = 0; i < rowSize; i++)
{
ptr2D[i] = new short[columnSize];
//Initialize the memory
for(unsigned int j = 0; j < columnSize; j++)
{
ptr2D[i][j] = 0;
}
}
// Assign type id and add to the list of 2D pointers
MemType mem2DType;
mem2DType.dataType = 0;
// Store the number of rows and columns
mem2DType.noOfRows = rowSize;
mem2DType.noOfColumns = columnSize;
mem2DType.noOfItems = 0;
// Insert the pointer into the map
_MemHandle2DPointer[(long) ptr2D] = mem2DType;
return ptr2D;
}
void ReleaseMemory (short** ptr2D)
{
// Releasing memory occupied by 2D pointer
if (ptr2D != NULL)
{
map < unsigned long, MemType >::iterator iter = _MemHandle2DPointer.find((long)ptr2D);
if (iter != _MemHandle2DPointer.end())
{
//cout<<" Releasing Memory occupied by 2D pointer \n";
_MemHandle2DPointer.erase((long)ptr2D);
for (unsigned int i = 0; i < iter->second.noOfRows; i++)
{
delete [] (short *) ptr2D[i];
}
delete [] (short **) ptr2D;
ptr2D = NULL;
}
}
}
int main()
{
short** dminImage = AllocateMemory(100,200);
ReleaseMemory (dminImage);
return 0;
}
I fixed the issue with this workaround.
void ReleaseMemory (short** ptr2D)
{
// Releasing memory occupied by 2D pointer
if (ptr2D != NULL)
{
map < unsigned long, MemType >::iterator iter = _MemHandle2DPointer.find((long)ptr2D);
if (iter != _MemHandle2DPointer.end())
{
//cout<<" Releasing Memory occupied by 2D pointer \n";
// _MemHandle2DPointer.erase((long)ptr2D);
for (unsigned int i = 0; i < iter->second.noOfRows; i++)
{
delete [] (short *) ptr2D[i];
}
_MemHandle2DPointer.erase((long)ptr2D);
delete [] (short **) ptr2D;
ptr2D = NULL;
}
}
}
I am confused as to what was causing the earlier error.
There is no provision to use smart pointers or any c++ 11 stuff.it's a legacy code.
You are erasing the map element for which you have the iterator, and then you still use the iterator. Don't do that. The iterator gets invalidated by erasing the element to which it points.
Related
I try to build a function which deletes the last element of an array. So I need an input array and its dimension, then delete the last term and obtain a new output array. I don't want that. My goal is to somehow make the output array the new input array. In other words, I want to overwrite the input array with the output array.
So if dimension is 4, I don't want to have a 4-dim array in the memory but only 3-dim table after the deletion.
void del (int* ptr_array, int dim) {
int* temp = ptr_array; //Hold the very first address of the input array.
ptr_array = new int[dim - 1]; // Let the address of the input array be
// the address of new output array. Overwritting.
for (int i = 0; i < dim - 1; i++) {
ptr_array = (temp+i); // Will it remember what is temp+1 if I have
// already overwritten the arrays?
ptr_array++;
}
//delete[] ptr_array; - this one is out of the questions - deletes now the input table.
}
Can you tell me what is wrong with this code? - in fact it doesn't change anything
in you function
for (int i = 0; i < dim - 1; i++) {
ptr_array = (temp+i); // Will it remember what is temp+1 if I have
// already overwritten the arrays?
ptr_array++;
}
does nothing, you wanted
for (int i = 0; i < dim - 1; i++) {
ptr_array[i] = temp[i];
}
Note the delete in your comment is invalid because you do not delete the result of a new[] but a pointer inside the allocated array
If the call is like
int * v = ...;
del(v);
// here v is unchanged
probably you wanted to modify v, in that case you can return the new array or to use an input-output variable using a reference
First possibility :
int* del (int* ptr_array, int dim) {
int* new_array = new int[dim - 1];
for (int i = 0; i < dim - 1; i++) {
new_array[i] = ptr_array[i];
}
delete[] ptr_array;
return new_array;
}
with
int * v = ...;
v = del(v);
Second possibility
void del (int*& ptr_array, int dim) {
int* new_array = new int[dim - 1];
for (int i = 0; i < dim - 1; i++) {
new_array[i] = ptr_array[i];
}
delete[] ptr_array;
ptr_array = new_array;
}
with
int * v = ...;
del(v);
// here v is the new array
Warning these codes suppose the input array has at least one element
However the use of an std::vector<int> does all of that for you and is more practical to use
std::vector<int> v;
...
v.resize(v.size() - 1);
or
std::vector<int> v;
...
v.pop_back();
I am studying the vector array with my assignment, and with this assignment I have some question that is about the two dimension vector array.
THE ASSIGNMENT is : List the current process with show up their parent-child relation.
Question
I want to pass the vector value just ppids[i] to do this I write it only write
vector<process*>
If my function parameter declare like
vector<vector<process*>>
it must write "ppids" so it is not my intent.
Error
Cannot convert 1 parameter from 'std::vector<process *,std::allocator<_Ty>>'to 'std::vector &'
So, here is my codes. (Just a part of my code)
Struct Vector :
struct process {
string procName;
DWORD procPid;
DWORD procPpid;
};
main vector, get process information on msdn API
std::vector <process*> myProcess;
part of main below...
//
// Group Vector by PPid
//****(here is 2 dimension vector)****
std::vector< std::vector< process* > > ppids;
int n = 0;
int index = 1;
for (int i = 0, size = tempPid.size(); i < size; ++i) {
ppids.push_back(vector<process*>());
for (int j = 0, size2 = myProcess.size(); j < size2; ++j) {
if (myProcess[j]->procPpid == tempPid[i]) {
ppids[n].push_back(myProcess[j]);
};
}
for (int k = 0, size3 = ppids[n].size(); k < size3; ++k)
{
_tprintf(TEXT("%d \t"), index);
index++;
_tprintf(TEXT("[%s]"), ppids[n][k]->procName.c_str());
_tprintf(TEXT("[%d]"), ppids[n][k]->procPid);
_tprintf(TEXT("[%d] \n"), ppids[n][k]->procPpid);
}
n++;
}
myProcess.clear();
the function is called on here.
// Combine vector
myProcess = ppids[0];
std::vector <process*> tmpProcess;
for (int i = 1, size = ppids.size(); i < size; ++i) {
tmpProcess = combine(myProcess, ppids[i]);
myProcess.clear();
myProcess = tmpProcess;
}
and finally, this is my function.
vector<process*> combine(vector<process*> tempA, vector<process*> tempB) {
std::vector <process*> alloProcess;
for (int i = 0, size = tempA.size(); i < size; ++i) {
if (tempA[i]->procPid == tempB[1]->procPpid)
{
alloProcess.push_back(tempA[i]);
for (int j = 0, size2 = tempB.size(); j < size2; ++j) {
alloProcess.push_back(tempB[j]);
}
}
else {
alloProcess.push_back(tempB[i]);
}
}
return alloProcess;
}
Full codes on here:
https://gist.github.com/anonymous/25e636086bbfacbec78508736935d3af
void function(vector< vector<process> > *matrix)
Specifies a pointer, it is essentially passed by reference. However, in C++, it's better to avoid pointers and pass a reference directly:
void function(vector< vector<process> > &matrix)
and
function(matrix1); // Function call
I just need to be sure I have enough memory available to the bi-dimensional array map. So I think I'd have to put a try catch bad:alloc in every row of map or perhaps with no throw would be more elegant. But I can't get with it. Any help would be appreciated...
I've read some articles about writing something like:
map[i] = new int [columns];
if (map[i] == NULL)
cout << “No enough memory”;
I don't like this solution and I've read that is not very reliable one.
fillmaze is a function called inside the constructor of maze..
void Maze::setupMaze(int r, int c, int l){
rows = r;
columns = c;
level = l;
fillMaze();
addBorders();
centerWalls();
getaway();
addWalls();
}
void Maze::fillMaze(){
map = new int* [rows];
for (int i = 0; i < rows; i++) {
map[i] = new int[columns];
}
//Inicializamos toda la tabla
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
map[i][j] = PASSAGE;
}
}
}
Also delete [] map is not enough right ? I'm doing in the destructor of the class:
Maze::~Maze(void)
{
for (int i = 0; i < rows; ++i)
delete[] map[i];
delete[] map;
}
This is why you should use std::vector<> as it will handle all the memory management for you correctly.
Issue 1: new never returns NULL (for pedants the normal new as used below). Also note in C++ we use nullptr not NULL for type safety.
map[i] = new int [columns];
if (map[i] == NULL) // This will never be NULL
cout << “No enough memory”; // So this will never print anything.
If fillmaze() is called from the constructor. Then if it throws an exception your destructor is never called. This means you have to deal with any allocation failure in place.
map = new int* [rows]; // could throw.
for (int i = 0; i < rows; i++) {
map[i] = new int[columns]; // could throw
}
So you have to handle and be able to detect what has been allocated and thus what needs to be dallocated.
try
{
map = nullptr; // Init to nullptr to make sure
// you can distinguish between valid state
// and what could have randomly been in memory.
map = new int* [rows]{nullptr}; // Initialize all elements to nullptr.
// If any throw you don't want your code
// to start releasing random pointers.
// calling delete on nullptr is fine.
for (int i = 0; i < rows; i++) {
map[i] = new int[columns]{PASSAGE};
}
}
catch(...) // catch all exceptions.
{
if (map != nullptr) { // You should only loop over
// map if it has been allocated.
for (int i = 0; i < rows; i++) {
delete [] map[i];
}
}
delete [] map; // delete the map.
throw; // rethrow exception
}
Your destructor is dine.
But you can simplify this by simply using a vector:
std::vector<std::vector<int>> maze{std::vector<int>{PASSAGE, columns}, rows};
Ok, so I'm quite new to C++ and I'm sure this question is already answered somewhere, and also is quite simple, but I can't seem to find the answer....
I have a custom array class, which I am using just as an exercise to try and get the hang of how things work which is defined as follows:
Header:
class Array {
private:
// Private variables
unsigned int mCapacity;
unsigned int mLength;
void **mData;
public:
// Public constructor/destructor
Array(unsigned int initialCapacity = 10);
// Public methods
void addObject(void *obj);
void removeObject(void *obj);
void *objectAtIndex(unsigned int index);
void *operator[](unsigned int index);
int indexOfObject(void *obj);
unsigned int getSize();
};
}
Implementation:
GG::Array::Array(unsigned int initialCapacity) : mCapacity(initialCapacity) {
// Allocate a buffer that is the required size
mData = new void*[initialCapacity];
// Set the length to 0
mLength = 0;
}
void GG::Array::addObject(void *obj) {
// Check if there is space for the new object on the end of the array
if (mLength == mCapacity) {
// There is not enough space so create a large array
unsigned int newCapacity = mCapacity + 10;
void **newArray = new void*[newCapacity];
mCapacity = newCapacity;
// Copy over the data from the old array
for (unsigned int i = 0; i < mLength; i++) {
newArray[i] = mData[i];
}
// Delete the old array
delete[] mData;
// Set the new array as mData
mData = newArray;
}
// Now insert the object at the end of the array
mData[mLength] = obj;
mLength++;
}
void GG::Array::removeObject(void *obj) {
// Attempt to find the object in the array
int index = this->indexOfObject(obj);
if (index >= 0) {
// Remove the object
mData[index] = nullptr;
// Move any object after it down in the array
for (unsigned int i = index + 1; i < mLength; i++) {
mData[i - 1] = mData[i];
}
// Decrement the length of the array
mLength--;
}
}
void *GG::Array::objectAtIndex(unsigned int index) {
if (index < mLength) return mData[index];
return nullptr;
}
void *GG::Array::operator[](unsigned int index) {
return this->objectAtIndex(index);
}
int GG::Array::indexOfObject(void *obj) {
// Iterate through the array and try to find the object
for (int i = 0; i < mLength; i++) {
if (mData[i] == obj) return i;
}
return -1;
}
unsigned int GG::Array::getSize() {
return mLength;
}
I'm trying to create an array of pointers to integers, a simplified version of this is as follows:
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
Now the problem is that the same pointer is used for j in every iteration. So after the loop:
array[0] == array[1] == array[2];
I'm sure that this is expected behaviour, but it isn't quite what I want to happen, I want an array of different pointers to different ints. If anyone could point me in the right direction here it would be greatly appreciated! :) (I'm clearly misunderstanding how to use pointers!)
P.s. Thanks everyone for your responses. I have accepted the one that solved the problem that I was having!
I'm guessing you mean:
array[i] = &j;
In which case you're storing a pointer to a temporary. On each loop repitition j is allocated in the stack address on the stack, so &j yeilds the same value. Even if you were getting back different addresses your code would cause problems down the line as you're storing a pointer to a temporary.
Also, why use a void* array. If you actually just want 3 unique integers then just do:
std::vector<int> array(3);
It's much more C++'esque and removes all manner of bugs.
First of all this does not allocate an array of pointers to int
void *array = new void*[2];
It allocates an array of pointers to void.
You may not dereference a pointer to void as type void is incomplete type, It has an empty set of values. So this code is invalid
array[i] = *j;
And moreover instead of *j shall be &j Though in this case pointers have invalid values because would point memory that was destroyed because j is a local variable.
The loop is also wrong. Instead of
for (int i = 0; i < 3; i++) {
there should be
for (int i = 0; i < 2; i++) {
What you want is the following
int **array = new int *[2];
for ( int i = 0; i < 2; i++ )
{
int j = i + 1;
array[i] = new int( j );
}
And you can output objects it points to
for ( int i = 0; i < 2; i++ )
{
std::cout << *array[i] << std::endl;
}
To delete the pointers you can use the following code snippet
for ( int i = 0; i < 2; i++ )
{
delete array[i];
}
delete []array;
EDIT: As you changed your original post then I also will append in turn my post.
Instead of
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
there should be
Array array;
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject( new int( j ) );
}
Take into account that either you should define copy/move constructors and assignment operators or define them as deleted.
There are lots of problems with this code.
The declaration void* array = new void*[2] creates an array of 2 pointers-to-pointer-to-void, indexed 0 and 1. You then try to write into elements 0, 1 and 2. This is undefined behaviour
You almost certainly don't want a void pointer to an array of pointer-to-pointer-to-void. If you really want an array of pointer-to-integer, then you want int** array = new int*[2];. Or probably just int *array[2]; unless you really need the array on the heap.
j is the probably in the same place each time through the loop - it will likely be allocated in the same place on the stack - so &j is the same address each time. In any case, j will go out of scope when the loop's finished, and the address(es) will be invalid.
What are you actually trying to do? There may well be a better way.
if you simply do
int *array[10];
your array variable can decay to a pointer to the first element of the list, you can reference the i-th integer pointer just by doing:
int *myPtr = *(array + i);
which is in fact just another way to write the more common form:
int *myPtr = array[i];
void* is not the same as int*. void* represent a void pointer which is a pointer to a specific memory area without any additional interpretation or assuption about the data you are referencing to
There are some problems:
1) void *array = new void*[2]; is wrong because you want an array of pointers: void *array[2];
2)for (int i = 0; i < 3; i++) { : is wrong because your array is from 0 to 1;
3)int j = i + 1; array[i] = *j; j is an automatic variable, and the content is destroyed at each iteration. This is why you got always the same address. And also, to take the address of a variable you need to use &
I am trying to resize a vector element of a structure and it causes segv. But when I did it individually for some small struct it worked fine. I am curious to know how it allocates memory to structure in which there is a vector element that could be resized. The below comment line causes segv in first iteration (type_index = 0).
Structure:-
struct thread_data {
dbPointer_t pObj;
dbObjId_t objId;
dbObjTypeId_t type;
dbObjId_t topCellId;
dbIteratorId_t objsIterId;
int precision;
int64_t shape_objs;
vector<vector<vector<PL_trp_header_t *> > > ps_hdrs;
int pool;
int num_layers;
int to_cell_id;
};
Below is the snippet of code:-
thread_data *t_data[types_length];
for(int type_index=0; type_index < types_length; ++type_index) {
t_data[type_index] = (thread_data*)malloc(sizeof(thread_data));
t_data[type_index]->pObj = NULL;
t_data[type_index]->objId = objId;
t_data[type_index]->type = shape_types[type_index];
t_data[type_index]->topCellId = topCellId;
t_data[type_index]->objsIterId = objsIterId;
t_data[type_index]->precision = nparams.unit_precision;
t_data[type_index]->shape_objs = 0;
t_data[type_index]->ps_hdrs.resize(num_layers); //this line causes segv
t_data[type_index]->pool = pool;
t_data[type_index]->num_layers = num_layers;
t_data[type_index]->to_cell_id = tocell_id;
for (int num = 0; num < num_layers; num++) {
t_data[type_index]->ps_hdrs[num].resize(index_limit);
for (int rows = 0; rows < index_limit; rows++)
t_data[type_index]->ps_hdrs[num][rows].resize(index_limit);
}
for(int i = 0; i < num_layers; i++) {
for (int rows = 0; rows < index_limit; rows++) {
for (int cols = 0; cols < index_limit; cols++) {
t_data[type_index]->ps_hdrs[i][rows][cols] = alloc_hdr(pool);
}
}
}
printf("In main: creating thread %d \n", type_index);
rc_thread = pthread_create(&threads[type_index], NULL, thread_fn, (void *) &t_data[type_index]);
if (rc_thread){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
free(t_data[type_index]);
}
I think you are allocating your data with malloc. In this case no constructors for your objects and theier members are called. This works with PODs but not with classes like vector. In the line with the error you try to access some unitialised memory like an vector. Try new and delete instead of mallac and free to solve this isue.