jg2000
jg2000

Reputation: 13

Problem with Memory Allocation while Using Threads

I am attempting to use with a structure that uses data allocation. Despite getting the correct outputs within each function, I am getting an overflow error when these functions are ran through a thread. The current code I have is:

#include <iostream> // cout, endl
#include <thread>   // thread

using namespace std;

// a structure to hold parameters to pass to a thread
struct StatData
{
    // the number of numbers
    int n;
    // the array of numbers
    double *numbers;
};

void average(StatData *data, double *avg) {
    int id;
    int size = data->n;
    double sum = 0.0;

    for(int i = 0; i < size; i++){
        sum += data->numbers[i];
    }
    *avg = sum / size;
}

void minimum(StatData *data, double *min) {
    int id;
    int size = data->n;
    *min = data->numbers[0];

    for(int i = 0; i < size; i++){
        if (*min > data->numbers[i]){
            *min = data->numbers[i];
        }
    }
}

void maximum(StatData *data, double *max) {
    int id;
    int size = data->n;
    *max = data->numbers[0];

    for(int i = 0; i < size; i++){
        if (*max < data->numbers[i]){
            *max = data->numbers[i];
        }
    }
}

int main(int argc, char** argv) {
    // checking if arguments were passed
    if (argc <= 1) {
        cout << "No numbers were passed." << endl;
        cout << "At least one number needs to be entered." << endl;
        return 1;
    }

    // declaring worker threads
    thread avg_t, min_t, max_t;

    // variables for values
    double avg_v;
    double min_v;
    double max_v;

    // initalizing data structure to hold numbers
    StatData data;
    data.n = argc - 1;                  // the amount of numbers passed
    data.numbers = new double[data.n];  // allocating space for nums

    // Filling in the array with numbers using atof
    for (int i = 0; i < data.n; i++) {
        data.numbers[i] = atof(argv[i+1]); // converting string to double
    }

    // creating average thread
    avg_t = thread(average, &data, &avg_v);

    // creating minimum thread
    min_t = thread(minimum, &data, &min_v);

    // creating maximum thread
    max_t = thread(maximum, &data, &max_v);

    // wating for threads to finish
    avg_t.join();
    min_t.join();
    max_t.join();

    printf ("The average value is %d\n", &avg_v);
    printf ("The minimum value is %d\n", &min_v);
    printf ("The maximum value is %d\n", &max_v);

    // freeing up dynamically allocated space
    delete[] data.numbers;
}

When I run a ./test with values of 47, 58, and 6 I get a printed statement of: The average value is -502425280 The minimum value is -502425288 The maximum value is -502425296

I'm not sure where I am going wrong that is causing the code to do this.

Upvotes: 1

Views: 137

Answers (1)

rustyx
rustyx

Reputation: 85341

You're printing addresses of the values (&avg_v is a pointer to avg_v, which when printed as %d, will print a part of the value of the pointer itself).

To print the double values themselves, simply do

    printf ("The average value is %lf\n", avg_v);
    printf ("The minimum value is %lf\n", min_v);
    printf ("The maximum value is %lf\n", max_v);

Note that %d is for printing integers, for floating point values use %f or %lf (the two are equivalent).

& is only needed in scanf because scanf takes addresses of variables. printf takes actual values, so no need to pass addresses to it (unless you want to print the address of course).


Having that sorted out, the program can arguably be made simpler by making use of more C++ standard library features. To name a few: std::vector, std::accumulate, std::min_element, std::max_element, std::async (which creates a thread for you and returns a future) and lambdas:

#include <iostream>
#include <thread>
#include <vector>
#include <numeric>
#include <algorithm>
#include <future>

int main(int argc, char** argv) {
    if (argc <= 1) {
        std::cout << "No numbers were passed.\n"
            "At least one number needs to be entered.\n";
        return 1;
    }

    std::vector<double> data;
    for (int i = 1; i < argc; i++) {
        data.push_back(atof(argv[i]));
    }

    auto avg_f = std::async([&] {
        return accumulate(data.begin(), data.end(), 0.0) / data.size();
    });
    auto min_f = std::async([&] {
        return *min_element(data.begin(), data.end());
    });
    auto max_f = std::async([&] {
        return *max_element(data.begin(), data.end());
    });

    // the 3 values are now being computed in parallel ...

    double avg_v = avg_f.get(); // get the values from futures (waits as necessary)
    double min_v = min_f.get();
    double max_v = max_f.get();

    std::cout << "The average value is " << avg_v << "\n";
    std::cout << "The minimum value is " << min_v << "\n";
    std::cout << "The maximum value is " << max_v << "\n";
}

Upvotes: 3

Related Questions