Access Object attributes in C++ [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am relatively new to C++ programming and I have done a code which is not performing as expected.
The code is a bit long [pasted at end for reference] but I will just point to my concern in the code:
I define an object of a class inside a while loop:
...
objVec[obj_i] = new ChipSeqRegion(refID, strand, midPoint, start, end, posArray, frac_posArray, negArray, frac_negArray);
//testing
cout<<"printing object number: "<<obj_i<<endl;
objVec[obj_i]->PrintID();
cout<<"printing frac pos array: "<<endl;
objVec[obj_i]->PrintFracPosArray();
obj_i++;
}
objVec[0]->PrintID();
cout<<endl;
objVec[0]->PrintFracPosArray();
cout<<endl;
objVec[1]->PrintID();
objVec[1]->PrintFracPosArray();
cout<<endl;
objVec[2]->PrintID();
objVec[2]->PrintFracPosArray();
}
In the above code fragment PrintID and PrintFracPosArray are just procedures[members of same class] to print contents of the variables/Arrays.
Now, If I try to print the object attributes refID and posArray inside the loop then all printed values come out different and as assigned and expected.
But outside the loop the printID attribute prints values uniquely [as expected] but posArray attributes just repeat the value last assigned in the loop.
I want to access all values uniquely outside the loop which is my concern.
I am sure this might be from a scope conflict or the way the variables are getting passed.
Any help will be great !!!
Thanks in advance.
A quick look on detailed code below can clarify any questions:
Detailed Code:[Apologies for bad presentation]
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <vector>
#include <iomanip>
#include <cmath>
#include "api/BamReader.h"
#include "api/BamWriter.h"
#include "api/BamAlignment.h"
#include "api/BamAux.h"
using namespace std;
using namespace BamTools;
BamReader reader;
BamAlignment al;
int const windowSize = 10;
int halfWindowSize = windowSize/2;
int const N = windowSize + 1;
//determine the gap score
float gap = -2;
//default value for matrix F
double negNum = -100000;
float F[N][N];
int xTraceBack[N][N];
int yTraceBack[N][N];
float maxScore;
int x_coord = 0;
int y_coord = 0;
//collections of arrays from chipSeq data after loading data
class ChipSeqRegion{
private:
int ref_id, mid_p, start_p, end_p;
char genomeStrand;
float* pos_array;
float* frac_positiveArray;
float* neg_array;
float* frac_negativeArray;
float* gap;
public:
ChipSeqRegion (int refID, char strand, int midPoint, int start, int end, float* posArray, float* frac_posArray, float* negArray, float* frac_negArray);
//accessors
int GetRefID(){return ref_id;}
int GetMidPoint(){return mid_p;}
void PrintID();
void PrintFracPosArray();
//destructor
~ChipSeqRegion(){
delete [] pos_array;
delete [] frac_positiveArray;
delete [] neg_array;
delete [] frac_negativeArray;
}
};
ChipSeqRegion::ChipSeqRegion(int refID, char strand, int midPoint, int start, int end, float* posArray, float* frac_posArray, float* negArray, float* frac_negArray){
ref_id = refID;
genomeStrand = strand;
mid_p = midPoint;
start_p = start;
end_p = end;
pos_array = posArray;
frac_positiveArray = frac_posArray;
neg_array = negArray;
frac_negativeArray = frac_negArray;
}
void ChipSeqRegion::PrintID(){
cout<<"ref id is: "<<ref_id<<endl;
}
void ChipSeqRegion::PrintFracPosArray(){
cout<<"this is raw pos data"<<endl;
for (int i = 0; i<windowSize; i++){
cout<<pos_array[i]<<'\t';
}
cout<<"this is frac data"<<endl;
for (int i = 0; i<windowSize; i++){
cout<<frac_positiveArray[i]<<'\t';
}
cout<<endl;
}
class ChipSeqLoader{
public:
void LoadData (string bamFileName, string coordFileName);
void GetRegions();
private:
string nameOfBamFile;
string nameOfCoordFile;
};
void ChipSeqLoader::LoadData(string bamFileName, string coordFileName){
nameOfBamFile = bamFileName;
nameOfCoordFile = coordFileName;
int obj_i = 0;
int objSize = 6;
ChipSeqRegion **objVec = new ChipSeqRegion* [objSize];
//reading coordinates
ifstream CoordFile;
char chrom[5], strand;
string sChr1, sChr2, withmotif, dot;
int start, end, midPoint;
float tag;
CoordFile.open(coordFileName.c_str());
if (CoordFile.is_open()){
while (!CoordFile.eof()){
CoordFile>>chrom;
CoordFile>>withmotif;
CoordFile>>dot;
CoordFile>>start;
CoordFile>>end;
CoordFile>>tag;
CoordFile>>strand;
CoordFile.ignore(200,'\n');
midPoint = (start+end)/2;
ostringstream convert1;
ostringstream convert2;
convert1<<chrom[3];
convert2<<chrom[4];
sChr1 = convert1.str();
sChr2 = convert2.str();
string sChrom;
sChrom = sChr1+sChr2;
int refID;
if (sChr1 =="X\0"){
refID = 19;
}else if (sChr1 == "Y\0"){
refID = 20;
}else{
refID = atoi(sChrom.c_str())-1;
}
int intStrand;
if (strand == '+'){
intStrand = 0;
}else if (strand == '-'){
intStrand = 1;
}
cout<<endl;
cout<<sChrom<<'\t'<<refID<<'\t'<<start<<'\t'<<end<<'\t'<<midPoint<<'\t'
<<strand<<'\t'<<intStrand<<endl;
//get information from the coordinates to return array
BamRegion region(refID, midPoint-600, refID, midPoint+600);
reader.SetRegion(region);
if(!reader.SetRegion(region)){
std::cout<<"could not set region."<<endl;
}
float posArray[windowSize];
float negArray[windowSize];
float frac_posArray[windowSize];
float frac_negArray[windowSize];
for (int index = 0; index < windowSize; index ++){
posArray[index] = 0;
negArray[index] = 0;
}
int posPosition;
int negPosition;
//if reverse strand, calculate and return the end position
//if positive strand, return the position
//put them in separate arrays
while (reader.GetNextAlignment(al)){
if (al.MapQuality>0 && al.IsReverseStrand()== true){
negPosition = al.GetEndPosition();
if (negPosition>=midPoint-halfWindowSize && negPosition <midPoint+halfWindowSize){
negArray[negPosition-midPoint+halfWindowSize]++;
}
}else if (al.MapQuality>0){
posPosition = al.Position;
if (posPosition>=midPoint-halfWindowSize && posPosition <midPoint+halfWindowSize){
posArray[posPosition-midPoint+halfWindowSize]++;
}
}
}
float posMax = 0, negMax = 0, max = 0;
float temp;
for (int i= 0; i<windowSize; i++){
temp = posArray[i];
if (temp>posMax){
posMax = temp;
}
}
for (int i = 0; i<windowSize; i++){
temp = negArray[i];
if (temp>negMax){
negMax = temp;
}
}
if (posMax>=negMax){
max = posMax;
}else{
max = negMax;
}
for (int i = 0; i<windowSize; i++){
frac_posArray[i] = posArray[i]/max;
frac_negArray[i] = negArray[i]/max;
}
objVec[obj_i] = new ChipSeqRegion(refID, strand, midPoint, start, end, posArray, frac_posArray, negArray, frac_negArray);
//testing
cout<<"printing object number: "<<obj_i<<endl;
objVec[obj_i]->PrintID();
cout<<"printing frac pos array: "<<endl;
objVec[obj_i]->PrintFracPosArray();
obj_i++;
}
objVec[0]->PrintID();
cout<<endl;
objVec[0]->PrintFracPosArray();
cout<<endl;
objVec[1]->PrintID();
objVec[1]->PrintFracPosArray();
cout<<endl;
objVec[2]->PrintID();
objVec[2]->PrintFracPosArray();
}
}
int main(int argc, char* argv[]) {
string bamFileName, coordFileName;
if (argc == 3){
bamFileName = argv[1];
coordFileName = argv[2];
}else{
std::cout << "Wrong number of arguments." <<endl;
return 1;
}
if (!reader.Open(bamFileName)){
std::cout<< "Could not open input Bam file." <<endl;
return 1;
}
if (!reader.LocateIndex()){
std::cout<<"Could not locate index file."<<endl;
return 1;
}
ChipSeqLoader loader;
loader.LoadData(bamFileName, coordFileName);
return 0;
}

All your objects point to the same piece of data, namely posArray and frac_posArray which are defined in the loop: if you look at the ChipSeqRegion class constructor, it accepts 2 arrays (with the very same names as the arrays cited above), ie. 2 pointers to sequences of data in memory. These pointers in the constructors are simply copied over in the instance fields:
pos_array = posArray;
frac_positiveArray = frac_posArray;
instead of copying the array contents, as it should probably be:
pos_array = new int[windowSize];
memcpy(pos_array,posArray, sizeof(int)*windowSize); // or use std::copy_n
frac_positiveArray = new int[windowSize];
memcpy(frac_positivearray,frac_posArray, sizeof(int)*windowSize); // or use std::copy_n
You probably will have the same issue with other arrays in the class.

Related

Heap corruption detected in C++ after removing strings

When running this code I get an error as shown in the image below.
I've tried running it on GCC compiler and it worked fine. But when running it on Visual Studio on Windows this error appeared:
Debug Error!
Program: C:\Users\yudab\source\repos\Project2\Debug\Project2.exe
HEAP CORRUPTION DETECTED: after Normal block (#153) at 0x014FD2E0.
CRT detected that the application wrote to memory after end of heap buffer.
After some testing it seems as the error only appears after trying to delete the second word.
#include <cstring>
#include <string>
#pragma warning(disable : 4996)
#include <iostream>
using namespace std;
void delStr(char**& lexicon, int& lexSize, char word[]);
void printAll(char** lexicon, int lexSize);
void retract2dArr(char**& arr, int& size);
int main() {
char** lexicon = new char* [3];
lexicon[0] = new char[6]{ "hello" };
lexicon[1] = new char[5]{ "test" };
lexicon[2] = new char[6]{ "world" };
int size = 3;
char removeTest[5] = { "test" }; //The first word I want to remove from the list
char removeWorld[6] = { "world" }; //The second word I want to remove from the list
printAll(lexicon, size); //First prints the entire list
delStr(lexicon, size, removeTest); //Removes the first word
delStr(lexicon, size, removeWorld); //Removes the second word
printAll(lexicon, size); //Prints the list after deleting the words
return 0;
}
void delStr(char**& lexicon, int& lexSize, char word[]) {
bool toDelete = false;
for (int i = 0; i < lexSize; i++) {
if (strcmp(lexicon[i], word) == 0) {
toDelete = true;
for (; i < lexSize - 1; i++) {
strcpy(lexicon[i], lexicon[i + 1]);
}
}
}
if (toDelete == true) {
delete[] lexicon[lexSize - 1];
retract2dArr(lexicon, lexSize);
}
return;
}
void printAll(char** lexicon, int lexSize) {
for (int i = 0; i < lexSize; i++) {
cout << lexicon[i];
if (i != lexSize - 1) {
cout << " ";
}
}
cout << endl;
return;
}
void retract2dArr(char**& arr, int& size) {
size--;
char** newArr = new char* [size];
for (int i = 0; i < size; i++) {
*(newArr + i) = *(arr + i);
}
printAll(newArr, size);
delete[] arr;
arr = newArr;
return;
}
You can't strcpy one string to another
if (strcmp(lexicon[i], word) == 0) {
toDelete = true;
for (; i < lexSize - 1; i++) {
strcpy(lexicon[i], lexicon[i + 1]);
}
}
As length will be different for each strings.
Example:
lexicon[0] = new char[6]{ "hello" };
lexicon[1] = new char[5]{ "test" }; // length is 4
lexicon[2] = new char[6]{ "world" }; // length is 5
3rd string won't fit in 2nd string, it causes out of bound access.
As kiran Biradar pointed out, the strcpy is to blame here. Although instead of copying each word in the lexicon to the memory allocated for the previous word, it would probably be better to simply move the pointers back withing the lexicon array.
Try something like this for your delStr function:
void delStr(char**& lexicon, int& lexSize, char word[]) {
for (int i = 0; i < lexSize; i++) {
if (strcmp(lexicon[i], word) == 0) {
delete[] lexicon[i];
for (; i < lexSize - 1; i++) {
lexicon[i] = lexicon[i + 1];
}
retract2dArr(lexicon, lexSize);
}
}
}
P.S. You didnt need to use a toDelete flag, you could call teh retract2dArr function within the first if.

how to assign an array to a pointer inside a structure without causing memory leakage

I am reading data from a file in a function and saving the data to a temporary array. Then I am passing the array to a pointer inside a structure. But when I check the output in the main function, the data that I am reading is compromised and there is memory leakage for some values.
I want to know how I can read the data in the main function without causing memory leakage.
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cstring>
using namespace std;
struct myWeather
{
wchar_t *cityName;
float *temperature, *pressure, *direction, *wind;
myWeather *next, *prev;
};
myWeather *readData();
int main()
{
myWeather *location, *currLoc;
location = readData();
currLoc = location;
for(int c=0; c<49; c++)
{
cout<< "temp value"<< c+1<<": "<< (*currLoc->temperature+c)<<endl;
}
for(int f=0; f<1441; f++)
{
cout<< "pressure value"<< f+1<<": "<< *(currLoc->pressure+f)<<endl;
}
for(int g=0; g<720; g++)
{
cout<< "Dir value"<< g+1<<": "<< *(currLoc->direction+g)<<endl;
}
for(int h=0; h<720; h++)
{
cout<< "Wind value"<< h+1<<": "<< *(currLoc->wind+h)<<endl;
}
return 0;
}
myWeather *readData()
{
myWeather *headPTR;
char cityText[80];
wchar_t cityNym[80];
string myCity;
float tmpData[49], prsData[1441], winData[720], dirData[720];
int len;
ifstream weatherFile ("Data.txt", ios::in);
headPTR = new myWeather;
getline(weatherFile, myCity);
len= myCity.length();
myCity.copy(cityText, len, 0);
cityText[len]='\0';
mbstowcs(cityNym, cityText, strlen(cityText)+1);
headPTR->cityName = new wchar_t;
headPTR->cityName= cityNym;
weatherFile>> cityText;
weatherFile>>len;
for(int a=0; a<49; a++)
{
weatherFile>>tmpData[a];
}
headPTR->temperature = new float;
headPTR->temperature = tmpData;
weatherFile>> cityText;
weatherFile>>len;
for(int b=0; b<1441;b++)
{
weatherFile>>prsData[b];
}
headPTR->pressure= new float;
headPTR->pressure= prsData;
weatherFile>> cityText;
weatherFile>>len;
for(int d=0; d<720; d++)
{
weatherFile>>dirData[d];
}
headPTR->wind= new float;
headPTR->wind= dirData;
weatherFile>> cityText;
weatherFile>>len;
for(int e=0; e<720; e++)
{
weatherFile>>winData[e];
}
headPTR->direction = new float;
headPTR->direction = winData;
weatherFile.close();
return headPTR;
}
First of all in your case instead using an array you should use old std::vector<float> and wstring (for cityName). This is exactly what you need.
In case of next and previous you can use std::unique_ptr for next and raw pointer for previous.
Basically it may look like this:
struct myWeather
{
std::wstring cityName;
std::vector<float> temperature, pressure, direction, wind;
std::unique_ptr<myWeather> next;
myWeather prev;
};
But on other hand it looks like you are implementing double linking list which is already provided, so IMO this aproach is better:
struct myWeather
{
std::wstring cityName;
std::vector<float> temperature, pressure, direction, wind;
};
using WeatherRecords = std::list<myWeather>;
So in fact you do not need any fancy pointers or use new delete operators.

Segmentation fault error with structures

I have no idea where the segmentation error is coming from ... Any ideas?
I am working with structures for an assignment
TestResult testResultFactory(std::string name, double mark)
{
//creating an object of TestResult
TestResult car;
car.name = name;
car.mark = mark;
return car;
}
Student studentFactrory(std::string name)
{
//Creating an object of student
Student house;
house.name = name;
house.testResults = 0;
house.numTestResults = 0;
return house;
}
void addTestResult(Student * student, std::string testName, double testMark)
{
//First we need to create a new array
(student->numTestResults)+=1;
TestResult *newTestArray = new TestResult[(student->numTestResults)];
//Now we loop through the old array and add it to the new one
int index = (student->numTestResults);
for (size_t i = 0; i < (index-1); i++)
{
newTestArray[i] = testResultFactory((student->testResults[i].name),(student->testResults[i].mark));
}
//Now we need to add the new student to the end of the array
newTestArray[index] = testResultFactory(testName, testMark);
(student->testResults) = newTestArray;
}
string studentBest(Student const * student)
{
//create variables as temps
string highestName;
double highestMark;
int index = (student->numTestResults);
//Setting the two variables to the first value
highestName = (student->testResults[0].name);
highestMark = (student->testResults[0].mark);
//Using a while loop to compare and get the best
for (size_t i = 0; i < index; i++)
{
if((student->testResults[i].mark)> highestMark)
{
highestMark = (student->testResults[i].mark);
highestName = (student->testResults[i].name);
}
}
//returning the string they want
string send = (highestName)+ " "+ doubleToString(highestMark)+ "%";
return send;
}
double studentAverage(Student const * student)
{
//Variables used as temps
double average = 0;
double counter = 0.0;
double running = 0;
int index = (student->numTestResults);
//Now we need to loop through each one and add to running and counter
for (size_t i = 0; i < index; i++)
{
counter++;
running += (student->testResults[i].mark);
}
//calculating the average;
average = (running)/counter;
return average;
}
void destroyStudent(Student * student)
{
delete [] (student->testResults);
(student->testResults)=0;
}
Subject subjectFactory(std::string name)
{
//Creating an object to use in subject factory
Subject lamp;
lamp.name = name;
lamp.numStudents = 0;
lamp.studentsAllocated = 0;
lamp.students = 0;
return lamp;
}
MY guess is that the error occurs because of an out of bounds array or an pointer not worked with correctly .
int getStudentIndex(Subject const * subject, std::string studentName)
{
int index;
int count = (subject->numStudents);
//loop to find the names and set index
for (size_t i = 0; i < count; i++)
{
if(studentName == ((subject->students[i].name)))
{
index = i;
}
else index = -1;
}
return index;
}
void addStudent(Subject * subject, std::string studentName)
{
//Variables as temps
Student *pointer =0;
int index = getStudentIndex(subject,studentName);
if(index != -1)
{
//Now we need to see if they are large enough
if((subject->studentsAllocated)==0)
{
//Set the allocated to 2
(subject->studentsAllocated) = 2;
pointer = new Student[2];
//Figure this out later
pointer[1] = studentFactrory(studentName);
(subject->students) = pointer;
}
else
{
//increase SA with 1.5
(subject->studentsAllocated) = (subject->studentsAllocated) * 1.5;
pointer = new Student[(subject->studentsAllocated)+1];
int count = (subject->studentsAllocated);
//Now we need to put all the other students in
for (size_t i = 0; i < count-1; i++)
{
pointer[i] = (subject->students[i]);
}
pointer[(subject->studentsAllocated)+1] = studentFactrory(studentName);
(subject->studentsAllocated) += 1 ;
}
//Once done just seet one equal to
(subject->students) = pointer;
}
else return;
}
void removeStudent(Subject * subject, std::string studentName)
{
//First get temps
int index = getStudentIndex(subject ,studentName);
int number = (subject->studentsAllocated);
int i = index;
//delete student
if(index == -1) return;
destroyStudent(&(subject->students)[index]);
//loop to shift the things
while (i<(number -1))
{
(subject->students)[i] = (subject-> students[i+1]);
}
//Removing the last one
(subject->numStudents) -= 1;
}
bool addTestResult(Subject * subject, std::string studentName, std::string testName, double testMark)
{
int index = getStudentIndex(subject ,studentName);
if(index != -1)
{
addTestResult(&(subject->students [index]),testName,testMark);
return true;
}
else
return false;
}
void printSubjectSummary(Subject const * subject)
{
cout<<(subject->name)<< ": with "<<(subject->numStudents)<<" students"<<endl;
//Variables to use in the loop
size_t indexLoop = subject->numStudents;
int i=0;
while (i< indexLoop)
{
cout<<(subject->students[i].name)<<" Average: "<<studentAverage(&(subject->students[i]))<<", Best: "<<studentBest(&(subject->students[i]))<<endl;
}
}
void destroySubject(Subject * subject)
{
//Variables
size_t indexLoop = subject->numStudents;
for (size_t i = 0; i < indexLoop; i++)
{
destroyStudent(&(subject->students[i]));
}
delete [] subject->students;
subject->students =0;
}
I can not seem to find where the segmentation error is coming from. Even restarted the whole assignment from scratch and still seem to get errors.
Can someone please help or indicate where the fault could be coming from.
Over here we have the structs.h file that is included in my code above
#ifndef STRUCTS_H
#define STRUCTS_H
struct TestResult{
double mark;//the test mark as a percentage
std::string name;//the test name
};
struct Student{
std::string name;
TestResult * testResults;//an arry of TestResults
size_t numTestResults;//the number of results for this student (also the size of the array)
};
struct Subject{
std::string name;
Student * students;//an array of Students
size_t numStudents;//the number of students added to the subject
size_t studentsAllocated;//the size of the Student arry(must never be smaller that numStudents)
};
#endif
There are so many logical errors in there that the root cause (or causes; there are quite a few candidates) could be pretty much anywhere.
getStudentIndex returns -1 unless the student is the last one in the array, and an indeterminate value for the first one you add, so adding the first student to a subject is undefined.
addStudent only adds a student if they're already taking the subject.
It also (for some inexplicable reason) allocates an array of two Students, leaving the first element uninitialised.
Using this first element is, of course, undefined.
In the other branch, it first claims that the number of allocated students is * 1.5, but then only allocates + 1.
This will undoubtedly lead to problems.
There is a recursion in addTestResult that will never terminate.
There are most likely other problems as well – this was just a quick glance.
Start with fixing these.
And do learn about constructors and destructors so you can get rid of those "factory" and "destroy" functions.

CUDA, a new initializer may not be specified for an array

So I currently have this code, but i get an error when compiling which is "a new initializer may not be specified for an array" but no where in my code am i declaring a NEW array. So i'm unsure where and how this problem is occurring. Here's the section of code where i think the problem is....
struct indvPasswords
{
int blockId;
int threadId;
list<char[1024]> passwords;
};
//22,500 individual blocks
int gridSize = 150;
//1024 threads contained within each block
int blockSize = 32;
int totalNumThreads = (gridSize*gridSize)*(blockSize*blockSize);
indvPasswords* pointerToPass = new indvPasswords[totalNumThreads];
Here is all the source code. It currently uses cuda for dictionary password look ups...
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <list>
using namespace std;
//////////////////////////////
// Constants //
//////////////////////////////
string password = "C:\\Users\\james\\Desktop\\password.txt";
string passwordListFile = "C:\\Users\\james\\Desktop\\10millionpasswordlist.txt";
struct indvPasswords
{
int blockId;
int threadId;
list<char[1024]> passwords;
};
//22,500 individual blocks
int gridSize = 150;
//1024 threads contained within each block
int blockSize = 32;
int totalNumThreads = (gridSize*gridSize)*(blockSize*blockSize);
indvPasswords* pointerToPass = new indvPasswords[totalNumThreads];
//Some serial setup first
string passwordFile()
{
string pwd = "";
ifstream fileStream(password);
if (fileStream.is_open()) {
getline(fileStream, pwd);
if (pwd != "") {
//Found a password
fileStream.close();
}
else {
cout << "No password found in file" << '\n';
}
}
else {
cout << "Cannot open password file" << '\n';
}
return pwd;
}
list<string> readPasswordList()
{
//open password list
string line = "";
ifstream fileStream(passwordListFile);
list<string> passwordList;
if (fileStream.is_open()) {
while (getline(fileStream, line)) {
passwordList.push_back(line);
}
}
else {
cout << "Cannot open password file" << '\n';
}
return passwordList;
}
void indexing()
{
list<string> passwords = readPasswordList();
int sizeOfList = passwords.size();
int modulus = sizeOfList%gridSize;
int runFlag = 0;
if (modulus != 0) {
//not evenly divided, pass overflow to first block
//Take the modulus off the size of password list, i.e.
//take a number of passwords from the top of the list.
//Temporarily store the passwords removed and give them
//as additional work to the first block.
list<string> temp;
for (int i = 0; i < modulus; i++) {
temp.push_back(passwords.front());
passwords.pop_front();
}
//Now evenly divide up the passwords amoungst the blocks
int numEach = passwords.size();
//The first for loop, iterates through each BLOCK within the GRID
for (int i = 0; i < (gridSize*gridSize); i++) {
//Set flag, for single run of first block list
if (i == 0) {
runFlag = 1;
}
//The second loop, iterates through each THREAD within the current BLOCK
for (int j = 0; j < (blockSize*blockSize); j++){
//setup the indexes
pointerToPass[i].blockId = i;
pointerToPass[i].threadId = j;
//The third loop, copies over a collection of passwords for each THREAD
//within the current BLOCK
for (int l = 0; l < numEach; l++) {
//Add the temporary passwords to the first block
if (runFlag == 1) {
for (int x = 0; x < temp.size(); x++){
//Convert
string tmp = temp.front();
char charTmp[1024];
strcpy(charTmp, tmp.c_str());
pointerToPass[i].passwords.push_back(charTmp);
temp.pop_front();
}
//Now never block run again
runFlag = 0;
}
//convert the passwords from string to char[] before adding
string tmp = passwords.front();
char charTmp[1024];
strcpy(charTmp, tmp.c_str());
pointerToPass[i].passwords.push_back(charTmp);
//now delete the item from passwords that has just been transfered
//over to the other list
passwords.pop_front();
}
}
}
}
else {
//Start to transfer passwords
//First calculate how many passwords each thread will be given to check
int numEach = sizeOfList / totalNumThreads;
//The first for loop, iterates through each BLOCK within the GRID
for (int i = 0; i < (gridSize*gridSize); i++) {
//The second loop, iterates through each THREAD within the current BLOCK
for (int j = 0; j < (blockSize*blockSize); j++){
//setup the indexes
pointerToPass[i].blockId = i;
pointerToPass[i].threadId = j;
//The third loop, copies over a collection of passwords for each THREAD
//within the current BLOCK
for (int l = 0; l < numEach; l++) {
//convert the passwords from string to char[] before adding
string tmp = passwords.front();
char charTmp[1024];
strcpy(charTmp, tmp.c_str());
pointerToPass[i].passwords.push_back(charTmp);
//now delete the item from passwords that has just been transfered
//over to the other list
passwords.pop_front();
}
}
}
}
}
//Now onto the parallel
__device__ bool comparison(indvPasswords *collection, char *password, int *totalThreads)
{
//return value
bool val = false;
//first calculate the block ID
int currentBlockId = blockIdx.y * gridDim.x + blockIdx.x;
//calculate the thread ID
int currentThreadId = currentBlockId * blockDim.y * blockDim.x + threadIdx.y * blockDim.x + threadIdx.x;
//Now go and find the data required for this thread
//Get the block
for (int i = 0; i < (int)totalThreads; i++) {
if (collection[i].blockId == currentBlockId) {
//Now check the thread id
if (collection[i].threadId == currentThreadId) {
//Now begin comparison
for (int j = 0; j < collection[i].passwords.size(); j++)
{
if (password == collection[i].passwords.front()) {
//password found!
val = true;
break;
}
//delete the recently compared password
collection[i].passwords.pop_front();
}
}
}
}
return val;
}
__global__ void kernelComp(indvPasswords *collection, char *password, int *totalThreads)
{
comparison(collection, password, totalThreads);
}
int main()
{
int size = totalNumThreads;
//grid and block sizes
dim3 gridDim(gridSize, gridSize, 1);
dim3 blockDim(blockSize, blockSize, 1);
//Get the password
string tmp = passwordFile();
//convert
char pwd[1024];
strcpy(pwd, tmp.c_str());
indexing();
//device memory pointers
indvPasswords* array_d;
char *pwd_d;
int *threadSize_d;
int *threads = &totalNumThreads;
//allocate host memory
pwd_d = (char*)malloc(1024);
//allocate memory
cudaMalloc((void**)&array_d, size);
cudaMalloc((void**)&pwd_d, 1024);
cudaMalloc((void**)&threadSize_d, sizeof(int));
//copy the data to the device
cudaMemcpy(array_d, pointerToPass, size, cudaMemcpyHostToDevice);
cudaMemcpy(pwd_d, pwd, 1024, cudaMemcpyHostToDevice);
cudaMemcpy(threadSize_d, threads, sizeof(int), cudaMemcpyHostToDevice);
//call the kernel
kernelComp << <gridDim, blockDim>> >(array_d,pwd_d,threadSize_d);
//copy results over
return 0;
}
When I compile your code on linux with the -std=c+=11 compiler switch for nvcc, I get a warning on this line:
for (int i = 0; i < (int)totalThreads; i++) {
in your comparison function. Given that totalThreads is a pointer passed to the function:
__device__ bool comparison(indvPasswords *collection, char *password, int *totalThreads)
that usage seems almost certainly broken. I'm pretty sure that warning should not be ignored and what you really want is:
for (int i = 0; i < *totalThreads; i++) {
The only error I get is on this line:
pointerToPass[i].passwords.push_back(charTmp);
but it doesn't seem to be exactly the error you are reporting:
$ nvcc -std=c++11 -o t1016 t1016.cu
/usr/include/c++/4.8.3/bits/stl_list.h(114): error: a value of type "const char *" cannot be used to initialize an entity of type "char [1024]"
detected during:
instantiation of "std::_List_node<_Tp>::_List_node(_Args &&...) [with _Tp=char [1024], _Args=<const std::list<char [1024], std::allocator<char [1024]>>::value_type &>]"
/usr/include/c++/4.8.3/ext/new_allocator.h(120): here
instantiation of "void __gnu_cxx::new_allocator<_Tp>::construct(_Up *, _Args &&...) [with _Tp=std::_List_node<char [1024]>, _Up=std::_List_node<char [1024]>, _Args=<const std::list<char [1024], std::allocator<char [1024]>>::value_type &>]"
(506): here
instantiation of "std::list<_Tp, _Alloc>::_Node *std::list<_Tp, _Alloc>::_M_create_node(_Args &&...) [with _Tp=char [1024], _Alloc=std::allocator<char [1024]>, _Args=<const std::list<char [1024], std::allocator<char [1024]>>::value_type &>]"
(1561): here
instantiation of "void std::list<_Tp, _Alloc>::_M_insert(std::list<_Tp, _Alloc>::iterator, _Args &&...) [with _Tp=char [1024], _Alloc=std::allocator<char [1024]>, _Args=<const std::list<char [1024], std::allocator<char [1024]>>::value_type &>]"
(1016): here
instantiation of "void std::list<_Tp, _Alloc>::push_back(const std::list<_Tp, _Alloc>::value_type &) [with _Tp=char [1024], _Alloc=std::allocator<char [1024]>]"
t1016.cu(108): here
1 error detected in the compilation of "/tmp/tmpxft_0000182c_00000000-8_t1016.cpp1.ii".
The solution to that issue is probably to not use an array as the list element type, as #ManosNikolaidis has already suggested.
However a bigger issue I see in your code is that you are attempting to use items from the c++ standard library in __device__ functions, and that won't work:
struct indvPasswords
{
int blockId;
int threadId;
list<char[1024]> passwords; // using std::list
};
...
__global__ void kernelComp(indvPasswords *collection, char *password, int *totalThreads)
^^^^^^^^^^^^^
// can't use std::list in device code
You should re-write your data structures used by the device to only depend on built-in types, or types derived from those built-in types.
There is a problem in this line :
list<char[1024]> passwords;
Arrays cannot be used in STL containers because it requires the type to be copy constructible and assignable. More details here. Try using a std::string for each password. Or even an array<char, 1024>.
You are actually using new to create an array here
indvPasswords* pointerToPass = new indvPasswords[totalNumThreads];
but I don't see anything wrong with that

Double free or corruption (fasttop) while executing Parallel version

I am trying to implement a serial algorithm in parallel manner using pthread.
Following is the code that i wrote -
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <cmath>
#include <sys/time.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <ctime>
#include <vector>
#include <map>
#include <sstream>
using namespace std;
double similarity_score(char a,char b);
double find_array_max(double array[],int length);
void insert_at(char arr[], int n, int idx, char val);
void checkfile(int open, char filename[]);
void *main_algo(void* rank);
double valueChanger(int p1 , int p2);
string read_sequence(ifstream& f);
int ind;
double mu,delta;
double H_max = 0.;
int N_a; // get the actual lengths of the sequences
int N_b;
int** H;
int count_gap = 6;
int matrix_i = 1;
double temp[4];
char *nameof_seq_a;
char *nameof_seq_b;
string seq_a,seq_b;
int bigCount;
int start_i;
int stop_i;
int start_j;
int stop_j;
int stopSituation;
int k;
map<int,int> mymap;
std::string strValue;
std::stringstream out;
std::stringstream out2;
double value;
int main(int argc, char** argv){
// read info from arguments
if(argc!=5){
cout<<"Give me the propen number of input arguments:"<<endl<<"1 : mu"<<endl;
cout<<"2 : delta"<<endl<<"3 : filename sequence A"<<endl<<"4 : filename sequence B"<<endl;
cout<<"5 : maximal length N of sequences"<<endl;exit(1);
}
mu = atof(argv[1]);
delta = atof(argv[2]);
/////////////////////////////////
// give it the filenames
nameof_seq_a = argv[3];
nameof_seq_b = argv[4];
//int N_max = atoi(argv[5]);
// read the sequences into two vectors:
ifstream stream_seq_b; // first define the input-streams for seq_a and seq_b
stream_seq_b.open(nameof_seq_b); // the same for seq_b
checkfile(! stream_seq_b,nameof_seq_b);
seq_b = read_sequence(stream_seq_b);
ifstream stream_seq_a;
stream_seq_a.open(nameof_seq_a); // open the file for input
checkfile(! stream_seq_a,nameof_seq_a); // check, whether the file was opened successfully
seq_a = read_sequence(stream_seq_a);
// string s_a=seq_a,s_b=seq_b;
N_a = seq_a.length(); // get the actual lengths of the sequences
N_b = seq_b.length();
cout<<"N_a length "<<N_a<<endl;
cout<<"N_b length "<<N_b<<endl;
////////////////////////////////////////////////
// initialize H
int temp1 = N_a+1;
int temp2 = N_b+1;
// call to main algorithm
bigCount = N_a;
stopSituation = (N_a + N_b -1) / count_gap;
cout<<"--------Big Count----"<<bigCount<<endl;
cout<<"--------stopSituation----"<<stopSituation<<endl;
//cout<<"--------Matrix_i-------"<<matrix_i<<endl;
while(matrix_i <= stopSituation+1){
//cout<<"--------MATRIX_I----"<<matrix_i<<endl;
pthread_t myThreads[matrix_i];
for(k = 1; k < matrix_i +1 ; k++){
if(k == 1){
start_i = 1;
stop_j = (count_gap * (matrix_i))+1;
}
else if(k == matrix_i){
start_i = (count_gap * (k-1)) + 1;
stop_j = count_gap +1;
}
else{
start_i = (count_gap * (k-1)) + 1;
stop_j = (count_gap * ((matrix_i - k)+1))+1;
}
start_j = (count_gap * (matrix_i - k))+1;
stop_i = (count_gap * k)+1;
//main_algo();
pthread_create(&myThreads[k], NULL,main_algo, (void*)k);
}
//wait until all threads finish
for(k = 1; k<matrix_i+1; k++){
pthread_join(myThreads[k],NULL);
}
//sleep(1);
if(matrix_i > 1)
{
}
matrix_i++;
}
// Print the matrix H to the console
cout<<"**************** Max is = "<<H_max<<endl;
mymap.clear();
} // END of main
/////////////////////////////////////////////////////////////////////////////
// auxiliary functions used by main:
/////////////////////////////////////////////////////////////////////////////
void checkfile(int open, char filename[]){
if (open){cout << "Error: Can't open the file "<<filename<<endl;exit(1);}
else cout<<"Opened file "<<filename<<endl;
}
/////////////////////////////////////////////////////////////////////////////
double valueChanger(int p1 , int p2){
out.str(std::string());
out2.str(std::string());
out << p1;
out2 << p2;
strValue = out.str()+out2.str();
double value_new = atoi(strValue.c_str());
return value_new;
}
void *main_algo(void* rank){
//void main_algo(){
// algorithm
for(int i=start_i;i<stop_i;i++){
if(i > N_a) {
break;
}
for(int j=start_j;j<stop_j;j++){
if(j > N_b){
break;
}
int iCheck = i-1;
int jCheck = j-1;
value = valueChanger(iCheck , jCheck);
//double myVal = H[iCheck][jCheck];
double myVal;
if ( mymap.find(value) == mymap.end() ) {
// not found
myVal = 0;
} else {
// found
myVal = mymap.find(value)->second;
}
if(seq_a[i-1]==seq_b[j-1]){
temp[0]= myVal+1.0;
}
else{
temp[0]= myVal-mu;
}
value = valueChanger(i-1 , j-1);
if ( mymap.find(value) == mymap.end() ) {
// not found
temp[1] = 0;
} else {
// found
temp[1] = mymap.find(value)->second-delta;
}
value = valueChanger(i , j-1);
if ( mymap.find(value) == mymap.end() ) {
// not found
temp[2] = 0;
} else {
// found
temp[2] = mymap.find(value)->second-delta;
}
temp[3] = 0.;
value = valueChanger(i , j);
mymap[value] = find_array_max(temp,4);
if( H_max < mymap[value] ){
H_max = mymap[value];
}
}
}
cout<<"Done"<< my_rank<<endl;
}
double similarity_score(char a,char b){
double result;
if(a==b){
result=1.;
}
else{
result=-mu;
}
return result;
}
/////////////////////////////////////////////////////////////////////////////
double find_array_max(double array[],int length){
double max = array[0]; // start with max = first element
for(int i = 1; i<length; i++){
if(array[i] > max){
max = array[i];
}
}
return max; // return highest value in array
}
/////////////////////////////////////////////////////////////////////////////
string read_sequence(ifstream& f)
{
// overflows.
string seq;
char line[5000];
while( f.good() )
{
f.getline(line,5000);
// cout << "Line:" << line << endl;
if( line[0] == 0 || line[0]=='#' )
continue;
for(int i = 0; line[i] != 0; ++i)
{
int c = toupper(line[i]);
// cout << char(c);
if( c != 'A' && c != 'G' && c != 'C' && c != 'T' )
continue;
seq.push_back(char(c));
}
}
return seq;
}
Here , when i execute this program , i get following error
*** Error in `./myProg': double free or corruption (fasttop): 0xb5300480 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x767e2)[0xb74e67e2]
/lib/i386-linux-gnu/libc.so.6(+0x77530)[0xb74e7530]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0xb7689aaf]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSs4_Rep10_M_destroyERKSaIcE+0x1b)[0xb76ee5ab]
/usr/lib/i386-linux-gnu/libstdc++.so.6(+0xad5f0)[0xb76ee5f0]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSs6assignERKSs+0x82)[0xb76efde2]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSsaSERKSs+0x23)[0xb76efe33]
./myProg[0x80499dc]
./myProg[0x8049c2f]
/lib/i386-linux-gnu/libpthread.so.0(+0x6d78)[0xb7730d78]
/lib/i386-linux-gnu/libc.so.6(clone+0x5e)[0xb75613de]
======= Memory map: ========
*** Error in `./myProg': double free or corruption (fasttop): 0x0829c8f8 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x767e2)[0xb74e67e2]
/lib/i386-linux-gnu/libc.so.6(+0x77530)[0xb74e7530]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0xb7689aaf]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSs4_Rep10_M_destroyERKSaIcE+0x1b)[0xb76ee5ab]
/usr/lib/i386-linux-gnu/libstdc++.so.6(+0xad5f0)[0xb76ee5f0]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSsaSERKSs+0x23)[0xb76efe33]
./myProg[0x80499dc]
./myProg[0x8049aee]
/lib/i386-linux-gnu/libpthread.so.0(+0x6d78)[0xb7730d78]
Aborted (core dumped)
Please feel free to copy and execute with following two statements -
1) g++ [name].cpp -o [name] -lpthread
2) ./[name] 1 1 filetoread.txt filetoread2.txt
Please update for any kind of mistake i am doing in writing my code.
Thank you !!!!
You need to protect any non-thread-safe variables (such as std::map) with a mutex (or other locking mechanism). Since you're using pthread, take a look at pthread_mutex_lock, pthread_mutex_unlock, and pthread_mutex_destroy.
Here are some notes if you want to go multithreading:
don't (unless you really need to) ... (multithreading brings a new world of complexity and problems)
.... If you really need to, don't use more threads than processors (this is becoming muddled in recent years with CPUs/cores/hyperthreads... but what I mean by processor is what the hardware or virtualization allows you to run in parallel) (otherwise you will have scheduling contention at the OS/hardware level)
lock (mutexes) all common data access.... (otherwise you will corrupt your common data)
.... but try to lock the least possible time. (because every time you lock it means that all your threads need to wait and they will be doing nothing).
and don't use locks unless you need to (because locking/unlocking is expensive)
Avoid locking by using processing queues (e.g. to deliver commands or deliver results across threads). Instead of locking while processing the command/result, you can lock only while inserting/removing from the queue.
Avoid locking by subdividing map-like single structure (with a single mutex) into an array of map-like structure (with an array of mutexes) indexed with a hash of the key of the original map. Instead of locking all threads, you will be locking only some of them.
If there's an unbalance between readers/writers, try a read/write mutex to minimize contention. Ths will allow multiple simultaneous readers or one writer.