Pthread_create segmentation faults when more than 12 threads? - c++

I have a C++ program that sums numbers from 0 to n, using t threads. N and T are passed as command line args. I am using a for loop that creates the pthreads and a second for loop that rejoins the main to them. The program executes fine when I use less than 11 or 12 threads. For example, on input 100 10, it returns 5050. When I use more than 11-12 threads, it causes a segmentation fault and crashes. I cant seem to figure out why. There are some lines in my code I was using for debugging, such as printing to the prompt, etc. Any tips are appreciated!
int n = 0;
int t = 0;
unsigned long gsum = 0;
pthread_mutex_t mutexsum;
void *sum(void *Index)
{
int index = (int)(int *) Index;
int threadSum = 0;
int k;
int lowerBound, upperBound; //used to find range of numbers to sum
//printf("I am here: %d \n",index);
if (index == t - 1) {
lowerBound = (n/t)*(t-1);
upperBound = n;
} else {
lowerBound = (n/t)*index;
upperBound = (n/t)*(index+1)-1;
}
for (k = lowerBound; k < upperBound + 1; k++) {
threadSum = threadSum + k;
}
// Critical Section
pthread_mutex_lock(&mutexsum);
gsum = gsum + threadSum;
pthread_mutex_unlock(&mutexsum);
pthread_exit((void*) 0);
}
int main(int argc, char* argv[]){
int i, k, j;
pthread_t sumThreads [t];
for(i = 1; i < argc; i++) {
if(i == 1)
n = atoi(argv[i]);
if(i == 2)
t = atoi(argv[i]);
}
if (n < 0 || t <= 0 || argc != 3) {
printf("Invalid or missing parameters! \n");
exit(0);
}
for (k = 0; k < t; k++) {
int nt = -1;
nt = pthread_create(&sumThreads[k], NULL, sum, (void*)k);
printf("%d \n", nt);
}
for (j = 0; j < t; j++) {
int rj = -1;
rj = pthread_join (sumThreads[j], NULL);
printf("%d \n", rj);
}
printf("Total Sum: %lu \n",gsum);
return 0;

You have initialized t to be zero at the top of your program, so this line:
pthread_t sumThreads [t];
is not allocating an array large enough to hold the thread identifiers. Thus, you have buffer overrun when storing the identifiers, and your are reading past the buffer in your thread_join loop.
You are using a feature called variable length array (or VLA) which became part of the C language in the 1999 revision to the standard. C++ has not adopted VLA, so you are using a compiler extension. If you want your code to be compliant with C++, you should use a vector instead.
std::vector<pthread_t> sumThreads;
// ...after t gets initialized
sumThreads.resize(t);

In c/c++ this type of code does not work:
int i=10:
int arr[i];
Avoid doing this. If this type of code was valid we would no longer need malloc..
This is exactly what you are trying to achieve.

Related

Heap corruption on dynamic programming problem

I'm getting an heap corruption error and I can't figure out where it is.
The problem is a coin change problem using dynamic programming. C is the array with the coin values, n is the size of the array, T is the target change, usedCoins is an array where the number of used coins should be mapped (i.e if C[1] = 2 and 3 2-coins are used, usedCoins[2] = 2 with all other indexes to 0.
Here's the code:
bool changeMakingUnlimitedDP(unsigned int C[], unsigned int n, unsigned int T, unsigned int usedCoins[]) {
static auto minCoins = new unsigned int[T+1]{UINT_MAX};
minCoins[0] = 0;
static auto lastCoin = new unsigned int[T+1]{0};
for(int i = 0; i < n; i++)
usedCoins[i] = 0;
for(int i = 0; i < n; i++){
for(int j = 1; j <= T; j++){
if(j >= C[i]){
minCoins[j-C[i]] == 0? minCoins[j] = 1 : minCoins[j] = std::min(1 + minCoins[j - C[i]], minCoins[j-C[i]]);
lastCoin[j] = i;
}
}
}
while(T > 0){
unsigned int last = lastCoin[T];
if(last == UINT_MAX || last < 0) return false;
usedCoins[last]++;
T -= C[last];
}
free(minCoins);
free(lastCoin);
return true;
}
When running on debug mode it goes through.

Porting code from C++ to C. How do I deal with this vector and range based loop

I am trying to port to C. Since there's no vectors in C, I used a normal array, but I don't know how I'm going to deal with the ranged based loop on line 18.
for (int u : d[i]) if (dfs(rev[u])) {
par[i] = u;
rev[u] = i;
return true;
}
Complete code:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
const int Maxn = 200;
vector<int> d[Maxn];
int par[Maxn];
int rev[Maxn];
bool vs[Maxn];
bool dfs(int i) {
if (i < 0) return true;
if (vs[i]) return false;
vs[i] = true;
for (int u : d[i]) if (dfs(rev[u])) {
par[i] = u;
rev[u] = i;
return true;
}
return false;
}
int main() {
ios_base::sync_with_stdio(false);
int n;
cin >> n;
string s;
getline(cin, s);
for (int i = 0; i < n; i++) {
getline(cin, s);
stringstream ss(s);
vector<int> mk(n, 1);
mk[i] = 0;
int x;
while (ss >> x)
mk[x] = 0;
for (int x = 0; x < n; x++)
if (mk[x])
d[i].push_back(x);
}
memset(par, -1, sizeof par);
memset(rev, -1, sizeof rev);
for (bool ok = true; ok; ) {
ok = false;
memset(vs, 0, sizeof vs);
for (int i = 0; i < n; i++)
if (par[i] < 0) {
ok |= dfs(i);
}
}
int ans = 0;
for (int i = 0; i < n; i++)
ans += (par[i] < 0);
cout << ans;
}
In C there is no std::vector, the closes would be an array.
int array[] = [ 1, 3, 5, 7, 9 ];
for(int i = 0; i < sizeof array / sizeof *array; ++i)
printf("array[%d] = %d\n", i, array[i]);
If you get a pointer of an array of int, the you have to pass the length of
the array as well, as sizeof arr / sizeof *arr works with arrays only.
void foo(in *array, size_t len)
{
for(int i = 0; i < len; ++i)
printf("array[%d] = %d\n", i, array[i]);
}
void bar(void)
{
int array[] = [ 1, 3, 5, 7, 9 ];
foo(array, sizeof array / sizeof *array);
}
edit 2
I noticed that you've posted your code and that d is declared as vector<int> d[Maxn];. Also taking in consideration your recent comment
So this is an array of vectors. Do you have any idea how i can work with arrays taking that in consideration in C
There a couple of ways to convert the array of vectors in C. But this depends
on your needs. If for example you know that all vectors are going to have the
same size (for example int vectsize = 100), then you can create a two
dimensional array with the sizes1
int Maxn = 200;
int vectsize = 100;
int d[Maxn][vectsize];
memset(d, 0, sizeof d); // initialize all elements with 0
// filling the data
for(int i = 0; i < Maxn; ++i)
{
for(j = 0; j < vectsize; ++j)
d[i][j] = get_value_for(i, j);
}
The the range-loop is very easy:
// assuming that the variables i, par, rev are valid, i between 0 and Maxn-1
for(int j = 0; j < vectsize; ++j)
{
int u = d[i][j];
if (dfs(rev[u])) {
par[i] = u;
rev[u] = i;
return true;
}
}
It gets a little more complicated if you only know one dimension, for example
every vector in the array could have a different size.
d[0].size() --> 10
d[1].size() --> 1
d[2].size() --> 3
...
The you can create an array of pointers to int, but you would have to keep
another array of ints with the length for every d[i] vector.
int Maxn = 200;
int *d[Maxn]; // pointer to int[Maxn] arrays
int vectsize[Maxn];
// initializing with 0
memset(d, 0, sizeof d);
memset(vectsize, 0, sizeof vectsize);
// filling the data
for(int i = 0; i < Maxn; ++i)
{
vectsize[i] = get_length_for(i);
d[i] = malloc(vectsize[i] * sizeof *d[i]);
if(d[i] == NULL)
// error handling
for(j = 0; j < vectsize[i]; ++j)
d[i][j] = get_value_for(i, j);
}
Note that I'm using here (and in the last example) get_length_for() and get_value_for() as placeholders2.
Now your range-base loop would look like this:
// assuming that the variables i, par, rev are valid, i between 0 and Maxn-1
for(int j = 0; j < vectsize[i]; ++j)
{
int u = d[i][j];
if (dfs(rev[u])) {
par[i] = u;
rev[u] = i;
return true;
}
}
At some point however you would have to free the memory:
for(int i = 0; i < Maxn; ++i)
free(d[i]);
The third option would be using a double pointer and using malloc/realloc
to allocate the memory. This is the more general solution, but you have to
take care of memory management and that can be sometimes difficult, especially when you
haven't programmed in C to much. But also in case where both dimension are unknown, this is the way to go:
int Maxn = get_some_maxn_value();
int **d, *vectsize;
d = malloc(Maxn * sizeof *d);
if(d == NULL)
// error handling
vectsize = malloc(Maxn * sizeof *vectsize);
if(vectsize == NULL)
// error handling,
// if you exit the function, don't forget
// to do free(d) first as part of the
// error handling
// initialize all elements with 0
memset(d, 0, Maxn * sizeof *d);
memset(vectsize, 0, Maxn * sizeof *vectsize);
// filling the data (the same as above)
for(int i = 0; i < Maxn; ++i)
{
vectsize[i] = get_length_for(i);
d[i] = malloc(vectsize[i] * sizeof *d[i]);
if(d[i] == NULL)
// error handling
for(j = 0; j < vectsize[i]; ++j)
d[i][j] = get_value_for(i, j);
}
In this case the range-loop would look exactly as for the array of pointers.
Freeing the memory is a little bit different though:
for(int i = 0; i < Maxn; ++i)
free(d[i]);
free(d);
free(vectsize);
Like I said earlier, which one of these three methods to use depends on the way
the original C++ code fills the values, how long the vectors are, etc. Judging
form the C++ code you posted, you read an integer from the user and store it
in n. Then you read more values from the user and push then in the vector
d[i] for all i between 0 and Maxn-1. It seems that all vectors have at
most length n, but because of
if (mk[x])
d[i].push_back(x);
they also could have less than n elements. That's why I think that the third
solution is preferable here.
Annotations
1Prior to C99, Variable Length Arrays (VLA) were not supported, so if you had the
dimension in a variable, you had to use malloc to allocate enough memory.
C99 supports VLAs, but I'm not quite sure how well supported they are and/or
whether your compiler supports them.
I personally don't use them in my code at all, that's why I really don't know. I compiled this examples with GNU
GCC 6.4.0 (on linux) and they worked fine.
The first two options use VLAs, if your compiler doesn't support that, then
you have to use the third option.
For more information about VLAs:
malloced array VS. variable-length-array
What's the difference between a VLA and dynamic memory allocation via malloc?
Variable length array
GCC manual: 6.19 Arrays of Variable Length (in case you ise GCC)
2How you really get this values depends on the original C++ code.
So far I've only looked very briefly over your C++ code. Using the values from
my example get_length_for(0) would return 10, get_length_for(1) would return 1,
get_length_for(2) would return 3, etc.
Assuming d[i] is a vector, this is a similar loop:
for (size_t s = 0; s < d[i].size(); s++)
{
int u = d[i][s];
if (dfs(rev[u]))
{
par[i] = u;
rev[u] = i;
return true;
}
}

Outputting differences in arrays

I have to make a code where the user inputs altitude readings and the code is supposed to output total climb, total descent, and net change. This is what I have below. I can't figure out how to code to have it output what I want it to.
#include <iostream>
using namespace std;
int main()
{
int array[2010], n, c, d, swap; //the array
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (c=0; c < n; c++)
scanf("%d", &array[c]);
for (c=0 ; c < ( n - 1 ); c++)
{
for (d = 0 ; d < n - c - 1; d++)
{
if (array[d] > array[d+1]) /* For decreasing order use < */
{
swap = array[d];
array[d] = array[d+1];
array[d+1] = swap;
}
}
}
printf("Sorted list in ascending order:\n"); //lists in order
for ( c = 0 ; c < n ; c++ )
printf("%d\n", array[c]);
// Returns minimum difference between any pair
int findMinDiff(int arr[2010], int n); //supposed to find differce
{
// Initialize difference as infinite
int diff = INT_MAX;
// Find the min diff by comparing difference
// of all possible pairs in given array
for (int d=0; d<n-1; d++)
for (int j=d+1; j<n; j++)
if (abs(array[d] - array[d--]) < diff)
diff = abs(array[d] - array[d--]);
cout<<"Total Climb "<<diff<<endl;
}
system("pause");
return 0;
}
I don't see why you are sorting the array. Sorting the array may cause problems in calculating the "total climb" and "total descent".
My understanding is that this assignment is about calculating the difference between two numbers and processing that difference.
void Process_Data(int array[2010], unsigned int quantity_of_climbs)
{
int total_climb = 0;
int total_descent = 0;
int minimum_change = INT_MAX;
for (int i = 0; i < quantity_of_climbs - 1; ++i)
{
const int height_change = array[i] - array[i+1];
if (height_change > 0) // A "climb"
{
total_climb += height_change;
}
if (height_change < 0) // A "descent"
{
total_descent = (-1) * height_change; // Change from negative to positive.
}
const int abs_height_change = abs(height_change);
if (abs_height_change < minimum_change)
{
minimum_change = abs_height_change;
}
}
// Display results
}

Implementation of Eisenberg-McGuire algorithm segmentation fault: 11 in C

I'm trying to understand the Eisenberg-McGuire algorithm and I found this program which implements it but when I run the program I get a segmentation fault.
Segmentation fault: 11
Here is the program
/* Eisenberg-McGuire algorithm: a software approach to N-process
mutual exclusion.
For description of Eisenberg-McGuire algorithm, see page 261 of
"Concurrent Systems - Operating Systems, Database and Distributed
Systems: An Inegrated Approach / Jean Bacon -- 2nd Edition".
Copyrigh (c) 2001 Xiao Zhang */
#include <stdlib.h>
#include <pthread.h>
#include <iostream>
using namespace std;
/**********************************************************************/
/* Eisenberg-McGuire's algorithm for N-process mutual exclusion */
/**********************************************************************/
class eis_mcg_mutex_t {
private:
int n;
enum procphase { out_cr, want_cr, claim_cr } *procphase;
int turn;
public:
/* Initialize the mutex data shared by N processes */
eis_mcg_mutex_t(int nproc)
{
n = nproc;
procphase = new enum procphase [n];
srand(time(0));
turn = (int) (1.0 * n * rand() / (RAND_MAX + 1.0));
for (int i = 0; i < n; i++)
procphase[i] = out_cr;
}
/* Entry protocol for process i */
void mutex_lock(int i) {
procphase[i] = want_cr;
int j = turn;
do
{
while (j != i)
{
if (procphase[j] == out_cr)
j = (j + 1) % n;
else
j = turn;
}
procphase[i] = claim_cr;
j = (j + 1) % n;
while (procphase[j] != claim_cr)
j = (j + 1) % n;
} while (!(j == i && (turn == i || procphase[turn] == out_cr)));
turn = i;
}
/* Exit protocol for process i */
void mutex_unlock(int i)
{
int j = (turn + 1) % n;
while (procphase[j] == out_cr)
j = (j + 1) % n;
turn = j;
procphase[i] = out_cr;
}
};
/**********************************************************************/
/* To test the Eisenberg-McGuire's algorithm, we write a simple */
/* program that creates N threads (processes) and then has each */
/* thread increment a global variable `counter' NLOOP times. The */
/* final value of `counter' is expected to be N * NLOOP. */
/**********************************************************************/
#define N 4 /* number of threads */
#define NLOOP 1000 /* number of times each thread loops */
int counter; /* this is cremented by the threads */
eis_mcg_mutex_t counter_in_use(N);
void *doit(void *arg)
{
int i, val;
int tid = *(int *)arg;
/* Each thread fetches, prints and increments the counter NLOOP times.
The value of the counter should increase monotonically. */
for (i = 0; i < NLOOP; i++) {
/* Replace pthread_mutex_lock() with Eisenberg-McGuire's
enter-critical-section procedure. */
counter_in_use.mutex_lock(tid);
/* Here is critical section */
val = counter;
counter = val + 1;
cout << tid << ": " << counter << endl;
/* Replace pthread_mutex_unlock() with Eisenberg-McGuire's
leave-critical-section procedure. */
counter_in_use.mutex_unlock(tid);
}
return NULL;
}
int main()
{
pthread_t tid[N];
int i;
for (i = 0; i < N; i++) pthread_create(&tid[i], NULL, doit, (void *)i);
for (i = 0; i < N; i++) pthread_join(tid[i], NULL);
return 0;
}
I can't understand what is causing the segmentation fault. Any help is appreciated. Thank You.
Fixed it.
for (i = 0; i < N; i++) pthread_create(&tid[i], NULL, doit, (void *)i);
should be
for (i = 0; i < N; i++) pthread_create(&tid[i], NULL, doit, (void *)&i);
missed the amperson operator for address.
Update:
I didn't pass the address now.
for (i = 0; i < N; i++) pthread_create(&tid[i], NULL, doit, (void *)i);
and in int doit(void *arg), changed int tid = *((int*)(&arg));
It works perfectly now.

Does C++ allow VLAs as function parameter

Given code is for generating a magic square in which i have used VLA for the function
create_magic_square(int n, int magic_square[n][n])
print_magic_square(int n, int magic_square[n][n])
#include <stdio.h>
void create_magic_square(int n, int magic_square[n][n]);
void print_magic_square(int n, int magic_square[n][n]);
int main()
{
int size;
printf("This program creates a magic square of a specified size");
printf("The size be an odd number between 1 and 99");
printf("Enter the size of magic square: ");
scanf("%d", &size);
if(size%2 == 0 || size < 0 || size > 99)
{
printf("Wrong Entry!!!");
return 0;
}
int square[size][size];
for( int i = 0; i < size; i++)
for(int j = 0; j < size; j++)
square[i][j] = 0;
create_magic_square(size, square);
print_magic_square(size, square);
return 0;
}
void create_magic_square(int n, int magic_square[n][n])
{
int row = 0, col = n/2;
magic_square[row][col] = 1;
while(magic_square[row][col] <= n*n)
{
int new_row = ((row - 1) + n) % n;
int new_col = ((col + 1) + n) % n;
if(magic_square[new_row][new_col] == 0)
{
magic_square[new_row][new_col] = magic_square[row][col] + 1;
row = new_row;
col = new_col;
}
else if(magic_square[new_row][new_col] != 0)
{
magic_square[row + 1][col] = magic_square[row][col] + 1;
row = row + 1;
}
}
}
void print_magic_square(int n, int magic_square[n][n])
{
for( int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
printf("%d ", magic_square[i][j]);
printf("\n\n");
}
}
when file saved with extension .cpp ,On compiling it is giving the following error:
When I changed this extension to .c, it worked fine.
What is the reason behind this?
I think VLAs are not allowed in C++, is it right?
NOTE: Check this link regarding VLAs as parameter:
Why use an asterisk "[*]" instead of an integer for a VLA array parameter of a function?
You can't use C-style array that way, all but the first extent must be compile-time constant.
What you can do is pass int *magic_square that points to a one-dimensional n*n array, and use a simple index-mapping function to get the linear index of the cell.
You tagged the question as C++, so you should know that
int square[size][size];
is not valid C++ either, though it's valid C99 and some compilers support it through extension.
For C++ I'd suggest to use std::vector<int> vec(size*size) as holder.