C++ pointer errors using pthreads - c++

I'm new at C++ language and I'm having some troubles with pointers/memory access in a program using pthreads.
Here is the deal: I have a class named Media, as below:
class Media
{
public:
int id;
int freeSpace = CAPACITY;
pthread_mutex_t mutex;
};
and a class named File, as below:
class File
{
public:
int id;
string name;
int size;
pthread_mutex_t mutex;
Media *media;
...
};
This doesn't matter much for the problem, but my program does the following: I have a vector with some random files with random sizes, and I want to put them inside the minimum quantity of medias using threads.
The problem is that I'm getting constantly "double free or corruption (fasttop)", "double free or corruption (!prev)" and "Segmentation fault" errors, and can't find out why. I'm not using mallocs nor frees, but I'm probably using pointers in a wrong way or something like that.
Here is a part of my main class, with the method used in the threads:
vector<Media> medias;
vector<File> files;
vector<File> processedFiles;
void* processFiles(void* args)
{
for (int i = 0; i < mediaQuantity; i++)
{
if (pthread_mutex_trylock(&medias[i].mutex) == 0)
{
Media* media = &medias[i];
for (int j = (int)files.size() - 1; j >= 0; j--)
{
if (pthread_mutex_trylock(&files[j].mutex) == 0)
{
if (files[j].size <= media->freeSpace)
{
media->freeSpace -= files[j].size;
files[j].media = media;
processedFiles.push_back(files[j]);
files.erase(files.begin() + j);
}
pthread_mutex_unlock(&files[j].mutex);
}
}
pthread_mutex_unlock(&medias[i].mutex);
}
}
}
int main()
{
...
Media* media;
...
pthread_t threads[threadQuantity];
pthread_barrier_init(&barrier, NULL, threadQuantity);
...
for (int i = 1; i <= mediaQuantity; i++)
{
media = new Media();
media->id = i;
medias.push_back(*media);
}
//Create threads
for(unsigned i = 0; i < threadQuantity; i++)
pthread_create(&threads[i], NULL, processFiles, NULL);
for(unsigned i = 0; i < threadQuantity; i++)
pthread_join(threads[i], NULL);
...
}
Somehow, I'm getting the double free or corruption and segmentation errors I mentioned in running time. Can anybody see anything wrong?
Sorry for the big question and thanks in advance!

Here is a hint after a quick look at your code, those lines:
processedFiles.push_back(files[j]);
files.erase(files.begin() + j);
are modifing collections that can be used by more than one thread simulanuously. You should add lock to prevent two threads from doing that.

Related

How to pass value to a Grandchild thread under a Child thread from Parent thread or Child thread in C++

I have a file.txt with the following values:
1234
567
8910
I want to create a program in c++, that creates x number of child threads with x being the number of lines in "file.txt". The child thread receives the line so it splits the line into digits and stores them in an array.
Then I want to create y number of grandchild threads under each child thread with y being the number of digits in that child thread array or received line value and pass each grandchild thread a single digit.
For example, for the above file.txt, my parent thread in main() will create 3 child threads. The first child thread will receive "1234", second "567", third "8910".
Then the first child will create 4 grandchild threads and pass the first grandchild thread "1", second "2", third "3", fourth "4".
Similarly, the second child will create 3 grandchild threads and pass the "5", "6", "7" digits.
And lastly, the third child will create 4 grandchild threads and pass the "8", "9", "1", "0" digits.
I want to pass all these values using multi-threading in parallel. I am able to get everything working fine till the child thread, and I am able to create the right amount of grandchild threads, but I am unable to pass them the values. Any help and guidance are much appreciated.
Here is my code: (please guide me to fix it)
#include <iostream>
#include <pthread.h>
#include <math.h>
#include <fstream>
#include <sys/wait.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
struct info {
int* digit = new int;
int* totalDigits = new int;
};
struct grandchildThreadData {
int GCTDdigit;
int GCTDgrandchildIndex;
int GCTDchildIndex;
info* GCTDinfo = new info;
info* GCTDparentInfo = new info;
};
struct childThreadData {
long int CTDlineValue;
int CTDchildIndex;
info* CTDinfo = new info;
};
// thread declaration
void* childThread(void*);
void* grandchildThread(void*);
// function to convert and store line to digits
int* digitSeparator(long int);
// MAIN PROGRAM
int main() {
// FILE OPENING
int totalLines{0};
ifstream file1("file.txt"), file2("file.txt");
string temp;
while (getline(file1, temp)) {
totalLines++;
}
file1.close();
long int* valueOnLine = new long int[totalLines];
int i =0;
while (!file2.eof()) {
file2 >> valueOnLine[i];
i++;
}
file2.close();
// FILE CLOSING
// THREAD START
static struct info* mainInfo = new info[totalLines];
pthread_t* child = new pthread_t[totalLines];
// will be used to pass values to child
static struct childThreadData* Carg = new childThreadData[totalLines];
// Creating Childthreads
for (int i = 0; i < totalLines; i++) {
Carg[i].CTDinfo[i] = mainInfo[i];
Carg[i].CTDchildIndex = i;
Carg[i].CTDlineValue = valueOnLine[i];
if (pthread_create(&child[i], nullptr, childThread, &Carg[i])) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
}
// Joining Childthreads
for (int i = 0; i < totalLines; i++) {
if (pthread_join(child[i], nullptr)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
}
delete[] valueOnLine;
delete[] child;
delete[] Carg;
return 0;
}
void* childThread(void* i) {
struct childThreadData* CTptr = (struct childThreadData*)i;
int totalDigits = log10((float)CTptr->CTDlineValue) + 1;
int* numberArray = digitSeparator(CTptr->CTDlineValue);
// THIS LINE WILL PUT TOTAL DIGITS INTO mainInfo
CTptr->CTDinfo[CTptr->CTDchildIndex].totalDigits[0] = totalDigits;
static struct info* childInfo = new info[totalDigits]; // This can be used to print modified info in grandchild
pthread_t* grandchild = new pthread_t[totalDigits];
static struct grandchildThreadData* GCarg = new grandchildThreadData[totalDigits];
// THIS LINE WILL PUT EACH DIGIT ON CORRECT LOCATION of mainInfo
for (int i=0; i< totalDigits; i++) {
CTptr->CTDinfo[CTptr->CTDchildIndex].digit[i] = numberArray[i];
}
// GRANDCHILD THREAD
for (int i = 0; i < totalDigits; i++) {
GCarg[i].GCTDinfo[i] = childInfo[i]; // grandchild to child communication but does not work
// or
GCarg[i].GCTDparentInfo[i] = CTptr->CTDinfo[i]; // grandchild to parent communication but does not work
GCarg[i].GCTDgrandchildIndex = CTptr->CTDchildIndex; // Here CTptr->CTDchildIndex should pass 0, 1, 2 to grandchild but I get different values
GCarg[i].GCTDchildIndex = i; // This line works fine for some reason
GCarg[i].GCTDdigit = CTptr->CTDinfo[CTptr->CTDchildIndex].digit[i]; // This line should pass the correct digit, but again, I am getting different results in grandchild
if (pthread_create(&grandchild[i], nullptr, grandchildThread, &GCarg[i])) {
fprintf(stderr, "Error creating thread\n");
}
}
//Joining GrandChildthreads
for (int i = 0; i < totalDigits; i++) {
if (pthread_join(grandchild[i], nullptr)) {
fprintf(stderr, "Error joining thread\n");
}
}
return nullptr;
}
void* grandchildThread(void* i) {
struct grandchildThreadData* GCTptr = (struct grandchildThreadData*)i;
// THIS LINE SHOULD PRINT THE DIGIT
cout << GCTptr->GCTDdigit;
return nullptr;
}
int* digitSeparator(long int number) {
int totalDigits = log10((float)number) + 1;
int* separatorPtr = new int[totalDigits];
int j = 0;
for (int i = totalDigits - 1; i >= 0; i--) {
long int divisor = pow((float)10, i);
long int digit = number / divisor;
number -= digit * divisor;
separatorPtr[j] = digit;
j++;
}
return separatorPtr;
}
The issue was caused by using static structs:
So, if we replace:
static struct childThreadData* Carg = new childThreadData[totalLines];
static struct grandchildThreadData* GCarg = new grandchildThreadData[totalLines];
with:
childThreadData* Carg = new childThreadData[totalLines];
grandchildThreadData* GCarg = new grandchildThreadData[totalLines];
It will work fine.
This is not an exhaustive list of the problems in the program but it deals some fundamental problems.
Your program does not check if file.txt is successfully opened. If it's not, the program will continue to run until it gets a signed integer overflow - which means that the program has undefined behavior.
If the file is successfully opened, you'll run into heap-buffer-overflow
// Creating Childthreads
for(int i = 0; i < totalLines; i++) {
Carg[i].CTDinfo[i] = mainInfo[i]; // <- here
That's because CTDinfo[i] is out of bounds when i > 0. CTDinfo is a pointer to one single info - not totalLines of infos.
Same thing below. CTDinfo can't be treated as an array since it's a pointer to a single info - and digit is a pointer to a single int - not an array of int.
// THIS LINE WILL PUT EACH DIGIT ON CORRECT LOCATION of mainInfo
for(int i = 0; i < totalDigits; i++) {
CTptr->CTDinfo[CTptr->CTDchildIndex].digit[i] = numberArray[i];
}
Suggestions:
Write a much smaller program to get the hang of threading.
Write a much smaller program to learn how to build up very complicated structures (if you are really required to do so). Use C++ classes, like std::vector. I doubt this program would need a single new/new[] if you replaced all the manual memory management with standard C++ containers. Things like info looks like there's been a misunderstanding. There is no reason why pointers should be used here:
struct info {
int* digit = new int;
int* totalDigits = new int;
};
Use std::thread and its support functions and classes instead of the platform specific C API in pthread.

I am getting a pointer being free but not allocated error when running make, make test in putty

I am very new to object oriented programming, pointer use and allocating memory in C++. I am working on an assignment for class and initially I had it pass the first three tests listed below by having an array, grade_array, that in the addScore function looked like grade_array[count -1] = grade. Then it would be used in the mean function.
I know this is not the correct way to go about this because I was getting seg faults, so I know I need to have an array, then create a new array (twice the size) that allocates more memory so that I can put the values of the first one into the new one, and then delete to not get memory leaks. The real problem I am having is I do not know if I am even close to correct on the way I am doing this. The error I am getting:
Running cxxtest tests (5 tests)testrunner(85436) malloc: *** error for object 0x107a87970: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
make: *** [test] Abort trap: 6
I have seen a lot of people having similar problems and posting about them on this very site I just cannot seem to fix mine. I saw that it could be that I made a new pointer and tried to them have them point to the same thing so when one deletes the other has nothing to delete or that my initializer is wrong as it doesn't do much. Like I said, very new to the topic so sorry if I have a million questions and so many errors. I have spent a lot of time on this already and was hoping I could maybe get some advice before I waste more time, thanks in advance!
Gradebook.h
#ifndef GRADEBOOK_H
#define GRADEBOOK_H
#include <string>
using namespace std;
class Gradebook {
public:
Gradebook();
Gradebook(const string& filename);
Gradebook(const Gradebook& that);
virtual ~Gradebook();
void initCount();
void addScore(double grade);
double getScoreAt(int i);
int getCount(int i);
string getSourceFile();
double getMean(); // change back to double
double getMin();
double getMax();
double getMedian();
double getStdDev();
int scoresInRange(double low, double high);
private:
string filename;
int* grade_array;
int new_size;
int count;
int count_tracker;
int* grade_point;
};
#endif
Gradebook.cpp
void Gradebook::initCount(){
count = 0;
}
Gradebook::Gradebook() {
}
Gradebook::Gradebook(const string& filename) : filename(filename) {
//this->filename = filename; // i beleive that filename(filename) does this line
//grade_array = new int[this->getCount(0) +1];
}
Gradebook::Gradebook(const Gradebook& that) {
}
Gradebook::~Gradebook() {
for ( int i = 0; i < this->getCount(0); i ++){
delete &grade_array[i];
}
delete grade_array;
}
void Gradebook::addScore(double grade) {
int count_tracker = this->getCount(1); //number of elements in array currently
// grade_array = new int[count_tracker ];
// grade_array = new int[1]; // grade_array is just a *array
grade_array[count_tracker -1 ] = grade; // array[0] is first not array[1]
new_size = count_tracker * 2;
int* new_array = new int[new_size];
for (int i = 0; i < count_tracker ; i++) {
new_array[i] = grade_array[i];
}
delete[] grade_array;
grade_array = new_array;
count_tracker = new_size;
}
double Gradebook::getScoreAt(int i) {
return grade_array[i];
}
int Gradebook::getCount(int i) {
if (i == 1){
count = count + 1;
}
else{
//don't want to add to the actual count
}
return count;
}
string Gradebook::getSourceFile() {
//ifstream foo;
//foo.open(filename);
return filename;
}
double Gradebook::getMean() {
double mean = 0;
count_tracker = this->getCount(0);
for (int i = 0; i < count_tracker ; i++){
//mean = (*(&(grade_array[i])- (bit_count))) + mean;
mean = grade_array[i] + mean;
}
return (mean/count_tracker);
}
GradebookTest.h
#ifndef GRADEBOOK_TEST_H
#define GRADEBOOK_TEST_H
#include <Gradebook.h>
#include <cxxtest/TestSuite.h>
class GradebookTest : public CxxTest::TestSuite {
public:
void testDefaultConstructor(){
string filename = "data1.txt";
Gradebook a(filename);
TS_ASSERT_EQUALS("data1.txt" , a.getSourceFile());
}
void testAddOne() {
Gradebook gb;
gb.initCount();
gb.addScore(110);
TS_ASSERT_EQUALS(120, gb.getScoreAt(1));
TS_ASSERT_DELTA(110, gb.getMean(), 0.001);
TS_ASSERT_EQUALS(4, gb.getCount(0) );
}
void testAddMultiple() {
Gradebook gb;
gb.addScore(75);
TS_ASSERT_EQUALS(1, gb.getCount(0) );
gb.addScore(85);
TS_ASSERT_EQUALS(2, gb.getCount(0));
TS_ASSERT_DELTA(85, gb.getMean(), 0.001);
}
#endif
I think the following is wrong
for ( int i = 0; i < this->getCount(0); i ++){
delete &grade_array[i];
}
You don't need this for loop since you only allocate memory for grad_array. One delete grade_array; is enough.

dynamic thread creation in c++

This is my code for multi threading (This is not the actual code but parts of different files at one place where I feel I am doing something wrong)
//main function
Example ExampleObj;
for (int i=0;i<10;i++)
{
pthread_t *service_thread = new pthread_t;
pthread_create(service_thread, NULL,start,&ExampleObj);
}
//start function
void *start(void *a)
{
Example *h = reinterpret_cast<Example *>(a);
h->start1();
return 0;
}
class Example
{
public:
void start1()
{
std::cout <<"I am here \n";
}
};
Code is not giving any error but it's not coming to start1 function as well.
Please let me know if I am creating the threads correctly or not.
If not, then what is the correct way.
There is no code that stops your main() from terminating the process before your worker threads have completed.
main() should look something like:
int main() {
Example ExampleObj;
// Start threads.
pthread_t threads[10];
for(size_t i = 0; i < sizeof threads / sizeof *threads; ++i) {
pthread_create(threads + i, NULL,start,&ExampleObj);
}
// Wait for the threads to terminate.
for(size_t i = 0; i < sizeof threads / sizeof *threads; ++i) {
pthread_join(threads[i], NULL);
}
}

Throttling C++ threads

I am trying to translate some C# code which creates N threads at a time and runs a function in each thread.
I have two problems:
-How do I limit N threads at a time?
-My linker doesnt appear to be recognising the static ints FastestMemory and SlowestMemory when I refer to them in my main method (when I print the values out at the end).
Could somebody please help?
So far I have:
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
class Test{
public:
static unsigned int FastestMemory;
static unsigned int SlowestMemory;
public:
Test(unsigned a, unsigned b){
FastestMemory = a;
SlowestMemory = b;
}
struct thread_data
{
int m_id;
thread_data(int id) : m_id(id) {}
};
static DWORD WINAPI thread_func(LPVOID lpParameter)
{
thread_data *td = (thread_data*)lpParameter;
int RepetitionNumber = td->m_id;
printf("thread with id = " + RepetitionNumber + '\n');
unsigned int start = clock();
vector<byte> list1;
vector<byte> list2;
vector<byte> list3;
for(int i=0; i<10000000; i++){
list1.push_back(57);
}
for (int i = 0; i < 20000000; i=i+2)
{
list2.push_back(56);
}
for (int i = 0; i < 10000000; i++)
{
byte temp = list1[i];
byte temp2 = list2[i];
list3.push_back(temp);
list2[i] = temp;
list1[i] = temp2;
}
unsigned int timetaken = clock()-start;
printf(RepetitionNumber + " Time taken in millisecs: " + timetaken);
if(timetaken < FastestMemory){
FastestMemory = timetaken;
}
if(timetaken > SlowestMemory){
SlowestMemory = timetaken;
}
return 0;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Test* t = new Test(2000000,0);
for (int i=0; i< 10; i++)
{
CreateThread(NULL, 0, Test::thread_func, new Test::thread_data(i) , 0, 0);
}
printf("Fastest iteration:" + Test::FastestMemory + '\n'); //Linker not recognising
printf("Slowest iteration:" + Test::SlowestMemory + '\n'); //Linker not recognising
int a;
cin >> a;
}
I'm not sure what you mean about "limit N threads at a time". Do you mean you want (for example) to only use, say, 5 threads to execute the 10 tasks in your question?
If so, you might want to use a thread pool of some sort. Windows has something like three separate thread pool APIs, along with I/O completion ports, which can also act as thread pools. It's also pretty easy to write a thread pool of your own if you find them lacking -- but the structure is quite a bit different from what you've posted.
The static unsigned int FastestMemory; declares but does not define the variable. You need to define it outside of the class definition:
class Test {
static unsigned int FastestMemory;
static unsigned int SlowestMemory;
// ...
};
unsigned int Test::FastestMemory = 0;
unsigned int Test::SlowestMemory = 0;
You are declaring but not defining your static ints.
Try:
class Test{
public:
static unsigned int FastestMemory;
static unsigned int SlowestMemory;
// ...
};
unsigned int Test::FastestMemory = 0;
unsigned int Test::SlowestMemory = 0;
As for defining N threads, looking at what you have so far, try using CreateThread to create individual threads and scale up as needed. Of course just doing this will give you a very basic and probably not very useful threading model. I suggest reading up on thread pools.

How can I prevent segmentation faults in my program?

I have a C assignment. It is a lot longer than the code shown below, and we are given the function prototypes and instructions only. I have done my best at writing code, but I am stuck with segmentation faults. When I compile and run the program below on Linux, at "735 NaN" it will terminate, indicating a segfault occurred. Why? What am I doing wrong? Basically, the program does not let me access table->list_array[735]->value and table->list_array[735]->key. This is of course the first segfault. There might be more following index 735.
#include <stdio.h>
#include <stdlib.h>
typedef struct list_node list_node_t;
struct list_node
{
char *key;
int value;
list_node_t *next;
};
typedef struct count_table count_table_t;
struct count_table {
int size;
list_node_t **list_array;
};
count_table_t* table_allocate(int size)
{
count_table_t *ptr = malloc(sizeof(count_table_t));
ptr->size = size;
list_node_t *nodes[size];
int k;
for(k=0; k<size; k++){
nodes[k] = NULL;
}
ptr->list_array = nodes;
return ptr;
}
void table_addvalue(count_table_t *table)
{
int i;
for(i=0; i<table->size; i++)
{
table->list_array[i] = malloc(sizeof(list_node_t));
table->list_array[i]->value = i;
table->list_array[i]->key = "NaN";
table->list_array[i]->next = NULL;
}
}
int main()
{
count_table_t *table = table_allocate(1000);
table_addvalue(table);
int i;
for(i=0; i<table->size; i++)
printf("%d %s\n", table->list_array[i]->value, table->list_array[i]->key);
return 0;
}
You're point ptr->list_array at a local variable (nodes) in table_allocate, which goes away when that function returns, leaving a dangling pointer. You probably want
list_node_t **nodes = malloc(size * sizeof(list_node_t *));
I recommend the routine use of valgrind(1) to prevent such problems from occurring.