I met a runtime error "double free or corruption" in my C++ program that calls a reliable library ANN and uses OpenMP to parallize a for loop.
*** glibc detected *** /home/tim/test/debug/test: double free or corruption (!prev): 0x0000000002527260 ***
Does it mean that the memory at address 0x0000000002527260 is freed more than once?
The error happens at "_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps);" inside function classify_various_k(), which is in turn inside the OpenMP for-loop inside function tune_complexity().
Note that the error happens when there are more than one threads for OpenMP, and does not happen in single thread case. Not sure why.
Following is my code. If it is not enough for diagnose, just let me know. Thanks for your help!
void KNNClassifier::train(int nb_examples, int dim, double **features, int * labels) {
_nPts = nb_examples;
_labels = labels;
_dataPts = features;
setting_ANN(_dist_type,1);
delete _search_struct;
if(strcmp(_search_neighbors, "brutal") == 0) {
_search_struct = new ANNbruteForce(_dataPts, _nPts, dim);
}else if(strcmp(_search_neighbors, "kdtree") == 0) {
_search_struct = new ANNkd_tree(_dataPts, _nPts, dim);
}
}
void KNNClassifier::classify_various_k(int dim, double *feature, int label, int *ks, double * errors, int nb_ks, int k_max) {
ANNpoint queryPt = 0;
ANNidxArray nnIdx = 0;
ANNdistArray dists = 0;
queryPt = feature;
nnIdx = new ANNidx[k_max];
dists = new ANNdist[k_max];
if(strcmp(_search_neighbors, "brutal") == 0) {
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps);
}else if(strcmp(_search_neighbors, "kdtree") == 0) {
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps); // where error occurs
}
for (int j = 0; j < nb_ks; j++)
{
scalar_t result = 0.0;
for (int i = 0; i < ks[j]; i++) {
result+=_labels[ nnIdx[i] ];
}
if (result*label<0) errors[j]++;
}
delete [] nnIdx;
delete [] dists;
}
void KNNClassifier::tune_complexity(int nb_examples, int dim, double **features, int *labels, int fold, char *method, int nb_examples_test, double **features_test, int *labels_test) {
int nb_try = (_k_max - _k_min) / scalar_t(_k_step);
scalar_t *error_validation = new scalar_t [nb_try];
int *ks = new int [nb_try];
for(int i=0; i < nb_try; i ++){
ks[i] = _k_min + _k_step * i;
}
if (strcmp(method, "ct")==0)
{
train(nb_examples, dim, features, labels );// train once for all nb of nbs in ks
for(int i=0; i < nb_try; i ++){
if (ks[i] > nb_examples){nb_try=i; break;}
error_validation[i] = 0;
}
int i = 0;
#pragma omp parallel shared(nb_examples_test, error_validation,features_test, labels_test, nb_try, ks) private(i)
{
#pragma omp for schedule(dynamic) nowait
for (i=0; i < nb_examples_test; i++)
{
classify_various_k(dim, features_test[i], labels_test[i], ks, error_validation, nb_try, ks[nb_try - 1]); // where error occurs
}
}
for (i=0; i < nb_try; i++)
{
error_validation[i]/=nb_examples_test;
}
}
......
}
UPDATE:
Thanks! I am now trying to correct the conflict of writing to same memory problem in classify_various_k() by using "#pragma omp critical":
void KNNClassifier::classify_various_k(int dim, double *feature, int label, int *ks, double * errors, int nb_ks, int k_max) {
ANNpoint queryPt = 0;
ANNidxArray nnIdx = 0;
ANNdistArray dists = 0;
queryPt = feature; //for (int i = 0; i < Vignette::size; i++){ queryPt[i] = vignette->content[i];}
nnIdx = new ANNidx[k_max];
dists = new ANNdist[k_max];
if(strcmp(_search_neighbors, "brutal") == 0) {// search
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps);
}else if(strcmp(_search_neighbors, "kdtree") == 0) {
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps);
}
for (int j = 0; j < nb_ks; j++)
{
scalar_t result = 0.0;
for (int i = 0; i < ks[j]; i++) {
result+=_labels[ nnIdx[i] ]; // Program received signal SIGSEGV, Segmentation fault
}
if (result*label<0)
{
#pragma omp critical
{
errors[j]++;
}
}
}
delete [] nnIdx;
delete [] dists;
}
However, there is a new segment fault error at "result+=_labels[ nnIdx[i] ];". Some idea? Thanks!
Okay, since you've stated that it works correctly on a single-thread case, then "normal" methods won't work. You need to do the following:
find all variables that are accessed in parallel
especially take a look at those that are modified
don't call delete on a shared resource
take a look at all library functions that operate on shared resources - check if they don't do allocation/deallocation
This is the list of candidates that are double deleted:
shared(nb_examples_test, error_validation,features_test, labels_test, nb_try, ks)
Also, this code might not be thread safe:
for (int i = 0; i < ks[j]; i++) {
result+=_labels[ nnIdx[i] ];
}
if (result*label<0) errors[j]++;
Because two or more processes may try to do a write to errors array.
And a big advice -- try not to access (especially modify!) anything while in the threaded mode, that is not a parameter to the function!
I don't know if this is your problem, but:
void KNNClassifier::train(int nb_examples, int dim, double **features, int * labels) {
...
delete _search_struct;
if(strcmp(_search_neighbors, "brutal") == 0) {
_search_struct = new ANNbruteForce(_dataPts, _nPts, dim);
}else if(strcmp(_search_neighbors, "kdtree") == 0) {
_search_struct = new ANNkd_tree(_dataPts, _nPts, dim);
}
}
What happens if you don't fall into either the if or the else if clauses? You've deleted _search_struct and left it pointing to garbage. You should set it to NULL afterward.
If this isn't the problem, you could try replacing:
delete p;
with:
assert(p != NULL);
delete p;
p = NULL;
(or similarly for delete[] sites). (This probably would pose a problem for the first invocation of KNNClassifier::train, however.)
Also, obligatory: do you really need to do all of these manual allocations and deallocations? Why aren't you at least using std::vector instead of new[]/delete[] (which are almost always bad)?
Your train method deletes _search_struct before allocating new memory to it. So the first time train is called, it is deleted. Is there code to allocate it before that call to train? You could end up trying to delete junk memory (we don't have the code to tell, though).
Related
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};
Sorry to ask for an answer to something so probably simple, but I can't figure this one out by myself, it seems.
So, I have a header file, like so:
#ifndef LEVELMAP_H
#define LEVELMAP_H
#include "Constants.h"
class LevelMap
{
public:
LevelMap(int map[MAP_HEIGHT][MAP_WIDTH]);
~LevelMap();
int GetTileAt(unsigned int h, unsigned int w);
private:
int** mMap;
};
#endif LEVELMAP_H
And a .ccp file like so:
#include "LevelMap.h"
// 0 = empty, 1 = blocked
LevelMap::LevelMap(int map[MAP_HEIGHT][MAP_WIDTH])
{
//Allocate memory for the level map.
mMap = new int*[MAP_HEIGHT];
for(unsigned int i = 0; i < MAP_HEIGHT; i++)
{
mMap[i] = new int[MAP_WIDTH];
}
//Populate the array.
for(unsigned int i = 0; i < MAP_HEIGHT; i++)
{
for(unsigned int j = 0; j < MAP_WIDTH; j++)
{
mMap[i][j] = map[i][j];
}
}
}
LevelMap::~LevelMap()
{
//Delete all elements of the array.
for(unsigned int i = 0; i < MAP_HEIGHT; i++)
{
delete [] mMap[i];
}
delete [] mMap;
}
int LevelMap::GetTileAt(unsigned int h, unsigned int w)
{
if(h < MAP_HEIGHT && w < MAP_WIDTH)
{
return mMap[h][w];
}
return 0;
}
Now, I get an access violation on the 'return mMap[h][w];' line, and I can't for the life of me figure out a solution.
For context, GetTileAt() is being used to detect if a certain tile on the screen should allow the player to collide with it or not.
You are not giving the exact error message that you get, but from the title I deduce that this is what you are looking at:
0xBAADF00D : Used by Microsoft's debug HeapAlloc() to mark uninitialized allocated heap memory
Which in your case would mean that mMap was never created. Try to delete all default constructors to find the exact error causing this. The default move, copy, and empty constructors will not work properly anyways, so it is good practice to delete them!
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.
i have to implement a small and simple game in c++ (a maze) and I have some problems right now.
Some snippets:
I've got an array of object pointers which represents my fields in the maze
Field*** maze;
init of the maze:
for (n = 0; n < MAZE_WIDTH; n++) {
this->maze[n] = new Field*[MAZE_HEIGHT];
for (p = 0; p < MAZE_HEIGHT; p++) {
this->maze[n][p] = new Field();
this->maze[n][p]->x = n;
this->maze[n][p]->y = p;
}
}
When creating the maze i need a list of already visited fields and a stack
so I did:
std::vector<Field*> visited;
std::vector<Field*> stack;
Then later I want to put a Field* into my stack
stack.push_back(neighbour);
But after this push all values in the object are wrong.
Even if i try
neighbour = stack.back();
all the values are completly different
I already red some threads about this topic and that's why i chose a vector of pointers and not objects.
Where is my fault?
Edit:
Some more snippets as requested:
Of course I allocate memory for the mate itself
this->maze = new Field**[MAZE_WIDTH];
Field is a simple class which looks like:
class Field {
public:
Field();
~Field();
bool w_left;
bool w_right;
bool w_front;
bool w_back;
unsigned int x;
unsigned int y;
private:
};
Since, you didn't posted the code of how you are obtaining the values,
compare to this, and try to find your problem...
std::vector<std::vector<Field*> > maze;
// Ini
for(int i = 0; i < MAZE_WIDTH; i++)
{
maze.push_back(std::vector<Field*>());
for(int j = 0; j < MAZE_HEIGHT; j++)
{
maze[i].push_back(new Field());
maze[i][j]->x = i;
maze[i][j]->y = j;
}
}
std::vector<Field*> visited;
// push the field [4,5] in a visited vector
visited.push_back(maze[4][5]);
// Clean up
for(size_t i = 0; i < maze.size(); i++)
{
for(size_t j = 0; j < maze[i].size(); j++)
delete maze[i][j];
}
Why declare the maze as Field***?
The C++ alternative is std::vector<std::vector<Field*> > maze;, and that's what you should use.
Okay, so here's the context. I've been up for almost a day straight now working on the legendary 8-puzzle problem. I have my heuristics down and my A_star algorithm down. We are required by the project spec to solve it using three different heuristic values. I can solve it for any one of the three individually, but when I go to solve them in succession, I get a ridiculous loop, and it never finds the correct successor state.
I believe my problem is with my pointers. I have a class, State, as defined below that has an int** array and a pointer to a State (its parent).
EDIT: I have to use int** as defined by the project specification, otherwise I would gladly use a pointer.
State (int **bd, State* prnt);
State (const State& other);
~State ();
I am then declaring them as such:
State::State(int **bd, State* prnt) {
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
}
// fill in the board
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = bd[i][j];
//board[i][j] =
}
}
// set the parent
parent = prnt;
}
State::State(const State& other) {
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
State::~State() {
//std::cout << "Deconstructing " << this << endl;
for (int i = 0; i < 3; i++)
delete board[i];
delete [] board;
delete parent;
parent = other.parent;
}
State::~State() {
//std::cout << "Deconstructing " << this << endl;
for (int i = 0; i < 3; i++)
delete board[i];
delete [] board;
delete parent;
}
State& State::operator=(const State &rhs) {
if (&rhs == this) {
return *this;
}
for (int i = 0; i < 3; i++) {
delete board[i];
}
delete [] board;
// allocate the board
board = new int*[3];
for (int i = 0; i < 3; i++) {
board[i] = new int[3];
}
// fill in the board
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//board[i][j] = rhs.board[i][j];
board[i][j] = rhs.getIntAtCoor(j, i);
}
}
//delete parent;
// set the parent
parent = rhs.parent;
// set g
g = rhs.g;
f = rhs.f;
hType = rhs.hType;
return *this;
}
I don't give the exact declarations -- some of it is simple like int = int. I just can't quite figure it out. I feel like either my delete parent is wrong or my parent = other.parent is wrong (or both).
Thank you for your time and help,
Tyler
Upgrading your code-style may force the errors to evaporate. In other words new and delete are error prone and should be avoided when better alternative exists.
For management of the cells consider:
std::shared_ptr: can be used to void the delete calls
std::vector can be used to avoid the new and delete calls
Note you should use it like std::vector<int> board( 3 * 3 ) and board.at( x + y * 3 ).
And best of all just use a static array int board[3][3]. No allocation at all.
Also child states do not own their parent states. It's the other way around. So child states shouldn't delete their parents. You can still safely keep a parent pointer, but make sure you cleanup the children before you allow a parent to go out of scope (deleted or otherwise). All of this cleaning and deleting doesn't neccessarily involve new at all. Your State class looks small enough that is doesn't matter if they are copied by value. In which case just have the parent use a std::vector<State> m_children and the compiler will take care of the rest.
You don't show the full definition of the copy constructor but I assume that the parent = other.parent line is in there. In that case, wouldn't the parent be responsible for its own lifetime and the delete parent in the destructor shouldn't exist at all.
Also note that you need to at least disable (private declaration) or implement the copy assignment operator.
Better still, use a vector of vector for your 2d array and let the language work for you.
Perhaps not a direct answer, but you are going against best practices for C++.
It's easier and definitely more maintainable to use vectors for this problem.
size_t row_sz = 3;
size_t col_sz = 3;
std::vector<int> board(row_sz * col_sz, 0);
int i = 0;
for (size_t r = 0; r < 0; r++)
for (size_t c = 0; c < 0; c++)
board[ r * row_sz + c ] = i++;
Multidimensional arrays are much easier handled with the above strategy as well. It just breaks less. If you really want the row/col access, write a wrapper around it.
struct Matrix {
int &operator()(size_t r, size_t c);
const int &operator()(size_t r, size_t c) const;
private:
std::vector<int> data;
};