I am trying to create a merge function for two array structures in c++ but am coming up with a bad access error that I don't know how to solve. The error comes up when I am trying to swap the element in the smaller array into the larger, merged array. The code doesn't even go through a single iteration. All three of i, j, and k remain at 0. Any help would be greatly appreciated! Here is the code:
struct Array
{
int *A;
int size;
int length;
};
void display(Array arr){
for (int i = 0; i < arr.length; i++)
std::cout << arr.A[i] << std::endl;
}
Array merge(Array arr1, Array arr2){
Array arr3;
arr3.length = arr1.length + arr2.length;
arr3.size = arr1.length + arr2.length;
int i = 0, j =0, k =0;
while(i <arr1.length && j < arr2.length){
if (arr1.A[i] < arr2.A[j])
{
arr3.A[k] = arr1.A[i]; //(The error is displayed here: Thread 1: EXC_BAD_ACCESS (code=1, address=0x28))
k++;
i++;
}
else if (arr2.A[j] < arr1.A[i])
{
arr3.A[k] = arr2.A[j];
k++;
j++;
}
}
for (; i< arr1.length; i++)
{
arr3.A[k]=arr1.A[i];
k++;
}
for (; i< arr2.length; j++)
{
arr3.A[k]=arr2.A[j];
k++;
}
return arr3;
}
int main() {
Array arr1;
arr1.size = 10;
arr1.length = 5;
arr1.A = new int[arr1.size];
arr1.A[0]= 2;
arr1.A[1]= 6;
arr1.A[2]= 10;
arr1.A[3]= 15;
arr1.A[4]= 25;
Array arr2;
arr2.size = 10;
arr2.length = 5;
arr2.A = new int[arr2.size];
arr2.A[0]= 3;
arr2.A[1]= 4;
arr2.A[2]= 7;
arr2.A[3]= 18;
arr2.A[4]= 20;
Array arr3 = merge(arr1, arr2);
display(arr3);
return 0;
}
Your Array arr3 does not allocate any memory for its int *A field. It's natural that it would not work.
Anyway, your implementation of Array is very poor. Don't reimplement arrays unless you have a good reason; use std::vector instead.
If you really need to implement an Array on your own, then learn about encapsulation, make a class with a constructor, and allocate/delete your data (*A) field properly. Remember, using pointers and heap memory without understanding them is a recipe for disaster.
Easy: arr3.A is not initialized. It's a pointer. What does it point to?
Suggestion: learn about dynamic memory allocation.
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 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.
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.
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).