Printing Value From Array in C++ - c++

I want to write a method in C++ which creates an array of monotonically increasing values. It has the inputs of int begin, int end, int interval.
In this example; method should return the array of [0,1,2,3,4,5,6,7,8,9,10]. When I print the results it should print out the first two indexes and get 0 and 1. However, when I print it, it gives 0 for the first one and 9829656 for the second one.
When I only print one index it is always correct, but when I print more than one index, every value except for the first printed one gives a different result. I think the other results are related to memory address since I used pointers.
#include <iostream>
using namespace std;
int* getIntervalArray(int begin, int end, int interval){
int len = (end - begin) / interval + 1;
int result[11] = {};
for (int i = 0; i <= len - 1; i++) {
result[i] = begin + interval * i;
}
return result;
}
int main(){
int begin = 0;
int end = 10;
int interval = 1;
int* newResult = getIntervalArray(begin, end, interval);
cout << newResult[0] << endl;
cout << newResult[1] << endl;
return 0;
}

You are returning a pointer to a local variable. You can instead return a std::vector by value as shown below:
#include <iostream>
#include <vector>
//return a vector by value
std::vector<int> getIntervalArray(int begin, int end, int interval){
int len = (end - begin) / interval + 1;
std::vector<int> result(len); //create a vector of size len
for (int i = 0; i <= len - 1; i++) {
result.at(i) = begin + interval * i;
}
return result;
}
int main(){
int begin = 0;
int end = 10;
int interval = 1;
std::vector<int> newResult = getIntervalArray(begin, end, interval);
//print out elements of returned vector
for(int i = 0; i < newResult.size(); ++i)
{
std::cout << newResult.at(i) << std::endl;
}
return 0;
}
The output of the above program can be seen here.

A possible solution dynamically allocating the local array, and returning it via a smart pointer:
#include <array>
#include <iostream>
#include <memory> // make_unique
auto getIntervalArray(int begin, int end, int interval)
{
int len = (end - begin) / interval + 1;
auto result{ std::make_unique<std::array<int, 11>>() };
for (int i = 0; i <= len - 1; i++) {
(*result)[i] = begin + interval * i;
}
return result;
}
int main()
{
int begin = 0;
int end = 10;
int interval = 1;
auto newResult{ getIntervalArray(begin, end, interval) };
std::cout << (*newResult)[0] << std::endl;
std::cout << (*newResult)[1] << std::endl;
std::cout << (*newResult)[2] << std::endl;
return 0;
}
Demo

Set the array variable in your function as static. This is because C++ does not support returning the address of a local variable.
static int result[11];

try this. also add deletion of the newResult
#include <iostream>
using namespace std;
int* getIntervalArray(int begin, int end, int interval){
int len = (end - begin) / interval + 1;
int* result = new int[len];
int lastValue = begin;
for (int i = 0; i <= len - 1; i++) {
result[i] = lastValue;
lastValue += interval;
}
return result;
}
int main(){
int begin = 0;
int end = 10;
int interval = 1;
int* newResult = getIntervalArray(begin, end, interval);
cout << newResult[0] << endl;
cout << newResult[1] << endl;
// add delete here.
return 0;
}

Related

Why segmentation fault with multithreading? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am working on a project about multithreading. Here Operation is a class which contains a type, a key, a time and an answer.
Here is my code:
#include <cstdlib>
#include <fstream>
#include <string>
#include <iomanip>
#include <pthread.h>
#include <vector>
#include "block.h"
using namespace std;
std::vector<Operation> *data;
block_bloom_filter filter(10000000, 0.01);
int ans[30000000];
void *test(void *arg)
{
int thread_id = *((int *)arg);
for (auto &op : data[thread_id])
{
if (op.type == 1)
{
filter.insert(op);
}
else
{
filter.query(op);
}
}
return 0;
}
int main(int argc, char **argv)
{
int k = atoi(argv[1]);
int *op_num = new int[k];
data = new vector<Operation>[k];
for (int i = 0; i < k; i++)
{
string tmp = "data" + to_string(i + 1) + ".in";
const char *s = tmp.c_str();
ifstream fin;
fin.open(s);
fin >> op_num[i];
//data[i] = new Operation[op_num[i]];
for (int j = 0; j < op_num[i]; j++)
{
string tmp1;
fin >> tmp1;
if (tmp1 == "insert")
{
Operation tmp2;
tmp2.type = 1;
fin >> tmp2.key >> tmp2.time;
tmp2.ans = -1;
data[i].push_back(tmp2);
}
else
{
Operation tmp2;
tmp2.type = 2;
fin >> tmp2.key >> tmp2.time;
tmp2.ans = -1;
data[i].push_back(tmp2);
}
}
fin.close();
}
auto start = std::chrono::high_resolution_clock::now();
int num_threads = k;
pthread_t *threads = new pthread_t[num_threads];
//auto **threads = new thread *[num_threads];
//pthread_t *threads = new pthread_t[k];
/*for (int i = 0; i < num_threads; i++)
{
threads[i] = new thread(test, i);
}
for (int i = 0; i < num_threads; i++)
{
threads[i]->join();
}*/
for (int i = 0; i < k; i++)
{
pthread_create(&threads[i], NULL, test, (void *)&(i));
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
//std::cerr << "duration = " << duration.count() << "us" << std::endl;
double time_used = duration.count() / 1e3;
std::ofstream f_time("time.out");
f_time << std::fixed << std::setprecision(3) << time_used << std::endl;
f_time.close();
for (int i = 0; i < k; i++)
{
for (int j = 0; j < op_num[i]; j++)
{
ans[data[i][j].time - 1] = data[i][j].ans;
}
}
ofstream fout;
fout.open("result.out");
for (int i = 0; i < 30000000; i++)
{
if (ans[i] >= 0)
fout << ans[i] << endl;
}
fout.close();
delete[] data;
delete[] threads;
delete[] op_num;
//pthread_exit(NULL);
}
My code can compile, but when running it shows segmentation fault and can only generate time.out no result.out. I've been working on it for a long time but still do not know why. Hope someone can help me.
Below is block.h
#include <algorithm>
#include <chrono>
#include <cmath>
#include <ctime>
#include <fstream>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
#include "Headers/MurmurHash3.h"
#include "xxHash/xxhash.c"
#define M_LN2 0.69314718055994530942
using namespace std;
typedef std::vector<bool> bit_vector;
class Operation
{
public:
int type; // 1: insert, 2: query
char key[17];
int time;
int ans;
};
int str_len = 16;
int cache_size = 64;
int block_size = 512;
int key_num = 10000000;
int slot_num = 1 << 27;
int hash_num = int((double)slot_num / key_num * M_LN2);
int block_num = (slot_num + block_size - 1) / block_size;
class bloom_filter
{
uint32_t size; // Probable Number of elements in universe
double fpr; // False positive rate
int m; // optimal size of bloom filter
int k; // Number of hash functions
bit_vector bloom;
public:
int get_size() { return size; }
double get_fpr() { return fpr; }
bloom_filter(int n, double fpr)
{
this->size = n;
this->fpr = fpr;
this->m = ceil(
-((n * log(fpr)) /
pow(log(2), 2.0))); // Natural logarithm m = −n ln p/(ln 2)2
// cout << m<< "\n";
this->k = ceil(
(m / n) * log(2)); // Calculate k k = (m/n) ln 2 􃱺 2-k ≈ 0.6185 m/n
// cout << k;
bloom.resize(m, false);
}
void insert(string S)
{
uint32_t *p = new uint32_t(1); // For storing Hash Vaue
const void *str = S.c_str(); // Convert string to C string to use as a
// parameter for constant void
int index;
// cout<<S.length()<<"\t"<<sizeof(str)<<"\n";
// cout<<S<<"\n";
for (int i = 0; i < k; i++)
{
// MurmurHash3_x64_128();
MurmurHash3_x86_32(str, S.length(), i + 1,
p); // String, String size
index = *p % m;
// cout<<*p<<"\t"<<index<<"\t";
bloom[index] = true;
}
// cout<<"\n";
// print();
}
/*void print()
{
for (int i = 0; i < bloom.size(); i++)
{
cout << bloom.at(i);
}
}*/
char query(string S)
{
uint32_t *p = new uint32_t(1); // For storing Hash Vaue
const void *str = S.c_str(); // Convert string to C string to use as a
// parameter for constant void
int index;
// cout << S.length() << "\t" << sizeof(str) << "\n";
// cout<<S<<"\n";
for (int i = 0; i < k; i++)
{
// MurmurHash3_x64_128();
MurmurHash3_x86_32(str, S.length(), i + 1,
p); // String, String size
index = *p % m;
// cout<<*p<<"\t"<<index<<"\t";
if (bloom[index] == false)
return 'N';
}
return 'Y';
}
};
class block_bloom_filter
{
int size; // Probable Number of elements in universe
double fpr; // False positive rate
int m; // optimal size of bloom filter
int k; // Number of hash functions
int s; // Number of bloom filters
bit_vector block_bloom;
int cache_line_size;
public:
int get_size() { return size; }
double get_fpr() { return fpr; }
block_bloom_filter(int n, double fpr)
{
this->size = n;
this->fpr = fpr;
this->m = ceil(
-((n * log(fpr)) /
pow(log(2), 2.0))); // Natural logarithm m = −n ln p/(ln 2)2
// cout << m << "\n";
this->k = ceil(
(m / n) * log(2)); // Calculate k k = (m/n) ln 2 􃱺 2-k ≈ 0.6185 m/n
// cout << k<<"\n";
this->cache_line_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE) * 8;
this->s =
ceil((double)m / cache_line_size); // Total number of Bloom Filters
// cout<<s<<"s valye\n";
block_bloom.resize(cache_line_size * s, false);
}
/*void insert(Operation &S)
{
int block_number;
int first_index, last_index;
int index;
uint32_t *p = new uint32_t(1); // For storing Hash Value
const void *str = S.key.c_str(); // Convert string to C string to use as a
// parameter for constant void
MurmurHash3_x86_32(str, sizeof(str), 1,
p); // String, String size//Find out block number
// if(s!=0)
block_number = *p % s;
first_index = block_number * cache_line_size;
for (int i = 1; i < k; i++)
{
// MurmurHash3_x64_128();
MurmurHash3_x86_32(str, S.key.length(), i + 1,
p); // String, String size
// cout<<*p<<"\n";
// cout<<"div="<<div << "\n";
index = (*p) % cache_line_size;
// cout<<index<<"\t";
// if(index>m) cout<<"\n"<<index<<"\tError detected\n";
// cout<<"\n"<<index<<"a\t\n";
// cout<<"\n"<<first_index<<"a\t\n";
// cout<<(index+first_index)<<"a\t\n";
block_bloom[index + first_index] = true;
}
// cout<<"\n";
// print();
}*/
XXH64_hash_t GetHash(const char *str)
{
return XXH3_64bits_withSeed(str, 16, /* Seed */ 123976235672331983ll);
}
void insert(Operation &s)
{
XXH64_hash_t hash = GetHash(s.key);
XXH64_hash_t hash1 = hash % m;
XXH64_hash_t hash2 = (hash / m) % m;
for (int i = 0; i < k; i++)
{
int pos = (hash1 + i * hash2) % m;
block_bloom[pos] = 1;
}
}
void query(Operation &s)
{
XXH64_hash_t hash = GetHash(s.key);
XXH64_hash_t hash1 = hash % m;
XXH64_hash_t hash2 = (hash / m) % m;
for (int i = 0; i < k; i++)
{
int pos = (hash1 + i * hash2) % m;
if (!block_bloom[pos])
{
s.ans = 0;
return;
}
}
s.ans = 1;
return;
}
};
for (int i = 0; i < k; i++)
{
pthread_create(&threads[i], NULL, test, (void *)&(i));
The third parameter to pthread_create(), the thread function's parameter, is a pointer to the loop variable. The thread function reads it, as follows:
void *test(void *arg)
{
int thread_id = *((int *)arg);
There are no guarantees whatsoever that this gets executed by the new execution thread before the parent execution thread increments i. When it comes to multiple execution threads, neither POSIX nor the C++ library gives you any guarantees as to the relative execution order of multiple threads.
All that pthread_create() guarantees you is that at some point in time later, which can before before or after pthread_create() returns, the new execution thread pops into existence and begins executing the thread function.
And it may very well be that one or more (if not all) execution threads finally begin executing, for real, after the for loop terminates and i gets destroyed. At which pointL when they do start executing, they will discover a pointer to a destroyed variable as their argument, and dereferencing it becomes undefined behavior.
Or, some of those execution threads get their gear running, at some point after they get created. By this time i's been incremented a couple of times already. So they both read the *(int *)arg, whose value is now -- who knows? And, just to make things interesting, both execution threads do this at the same time, and read the same value. At this point, the end result is already going to be garbage. It is clear that the intent here is for each execution thread getting a unique value for its parameter, but this very unlikely to happen here. There's nothing in the shown code that ensures that each execution threads actually gets its own unique thread_id.
Additionally, the original parent execution thread seems to assume that all the execution threads will all finish their job before the parent execution thread reads their results, and writes them out to a file.
Unfortunately, there's no code in the parent execution thread that appears to actually wait for all execution threads to finish. As soon as they're all started, it takes it on faith that they complete instantly, and it reads the partial results, and writes it out to a file:
auto stop = std::chrono::high_resolution_clock::now();
Well, the bad news here is that there's nothing that actually waits for all execution threads to actually stop, at this point. They're still running here. Even if the program manages to avoid crashing, the output results will be incomplete, and mostly junk.
ans[data[i][j].time - 1]
It appears that the value of .time here was originally read from the input file. There does not appear to be any bounds checking here. It's possible for this vector/array access to be out of bounds, resulting in an undefined behavior and a likely crash.
Also, another problem with the shown code: There are plenty of calls to new, but only some of those get deleted, resulting in multiple memory leaks. Inspecting the shown code, there is no clear reason to new anything, in the first place.
In conclusion, there are multiple problems with the shown code that result in undefined behavior, and any of them will be the reason for the observed crash. The shown approach is very much error-prone, and will require much more substantial work, and proper multi-threading support, and inter-thread sequencing, in order to get the sequence of all events happen in the correct order, across all the execution threads.

Why is the breakpoint showing the second value of my array to be a large number? Extra Credit work

Using nested while loops to count the number of each character in a given string and put those numbers in an array. Then finding the largest number in the array to determine the most common character. Returning this character to the caller.
When placing a breakpoint |down (noted below) Im getting the first array value to be correct, and the second to be incorrect.
I don't know where I'm going wrong. I do have to admit I'm quite burned out right now, so it could be something easy I'm overlooking. I don't know.
#include <iostream>
using namespace std;
#include <string>
#include <string.h>
char median(char *);
int main() {
const int SIZE = 50;
char thing[SIZE];
char *strPtr;
cout << " give me a string: " << endl;
cin.getline(thing, SIZE);
strPtr = thing;
char mostcommon = median(strPtr);
cout << mostcommon;
}
char median(char *strPtr) {
char holder = 'x';
int numberof[50];
int counter = 0;
int arrayspacecounter = 0;
int thirdcounter;
int fourthcounter;
while (*strPtr != '\0') {
holder = *strPtr;
while (*strPtr != '\0') {
strPtr++;
if (holder == *strPtr) {
counter++;
}
}
numberof[arrayspacecounter] = counter; //counts the number of each character.
arrayspacecounter++;
strPtr++;
counter = 0;
}
v
// break point set HERE
^
//find the largest number in numberof[]
int largest = 0;
for (thirdcounter = 0; thirdcounter <= 100; thirdcounter++) {
for (fourthcounter = 1; fourthcounter <= 100; fourthcounter++) {
if (largest < numberof[fourthcounter]) {
largest = numberof[fourthcounter];
}
}
}
return *(strPtr + (largest));
}
numberof is not initialised so will initially contain junk values, any unused entries will still contain junk values where your breakpoint is. Use:
int numberof[50] = { 0 };
Next fourthcounter goes up to 100 but you only have 50 elements in numberof, replace the magic number 50 with a constant like MAX_ELEMENTS:
const size_t MAX_ELEMENTS = 50;
int numberof[MAX_ELEMENTS] = { 0 };
....
for (thirdcounter = 0; thirdcounter < MAX_ELEMENTS; thirdcounter++)
{
for (fourthcounter = 1; fourthcounter < MAX_ELEMENTS; fourthcounter++)
{
Alternatively just use the arrayspacecounter you have created already:
for (thirdcounter = 0; thirdcounter < arrayspacecounter; thirdcounter++)
{
for (fourthcounter = 1; fourthcounter < arrayspacecounter; fourthcounter++)
{
I'm not sure why you have two for loops at the end? The outer one seems redundant. Fixing various other bugs results in the working function:
char median(const char* strPtr)
{
const size_t MAX_ELEMENTS = 50;
int numberof[MAX_ELEMENTS] = { 0 };
int counter = 0;
int arrayspacecounter = 0;
int fourthcounter;
const char* temp = strPtr;
while (*temp != '\0')
{
const char* holder = temp;
while (*temp != '\0')
{
temp++;
if (*holder == *temp)
{
counter++;
}
}
numberof[arrayspacecounter] = counter; //counts the number of each character.
arrayspacecounter++;
temp = holder;
temp++;
counter = 0;
}
//find the largest number in numberof[]
int largest = 0;
for (fourthcounter = 1; fourthcounter < arrayspacecounter; fourthcounter++)
{
if (numberof[largest] < numberof[fourthcounter])
{
largest = fourthcounter;
}
}
return *(strPtr + (largest));
}
Your code could be much simpler though:
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
char median(const char*);
int main()
{
char mostcommon = median("test");
std::cout << mostcommon;
}
char median(const char* strPtr)
{
std::map<char, int> frequencies;
for (auto ch = strPtr; *ch != '\0'; ch++)
{
frequencies[*ch]++;
}
auto max = std::max_element(frequencies.begin(), frequencies.end(), [](const auto& a, const auto& b) { return a.second < b.second; });
return max->first;
}
Your program segfaults in median somewhere, my guess is that you're trying to use a position outside of the boundaries of your array somewhere.
If all you're wanting to count frequency try something simpler, like this for example.
#include <string>
#include<iostream>
int main()
{
std::string phrase;
std::cout << "Enter a phrase \n";
std::getline(std::cin,phrase);
int a = 'A'; //index 0 of your array
int count=0;int max=0;
int counter[26] = {0}; //array that will hold your frequencies
char highestFreq;
for(char c:phrase) {
if(!isspace(c)) count = ++counter[int(toupper(c))-a];
if(count>max) max=count, highestFreq=c;
}
std::cout << "max is: "<<max << ". The letter is '"<< highestFreq << "'.\n"<< std::endl;
}

Passing Swaps and Comparisons into quicksort function

I'm making this program where I have to count the number of swaps and comparisons a quick sort function, and we have to pass the swaps and comps to the function. I'm not too sure how to do this. I have it so it can be done without passing anything to it, as shown below.
#include <iostream>
#include <ctime>
#include <stdlib.h>
#include <math.h>
using namespace std;
struct SwapandComp {
int swaps;
int comps;
};
const long ARRAY_SIZE = 5000;
int totalSwaps = 0;
int totalComps = 0;
int partition(int[], int, int) //add parameters int& swap and int& comp
SwapandComp quickSort(int[], int, int) //also add parameters for int& swap and int& comp
int main() {
SwapandComp qui;
long masterAry[ARRAY_SIZE] = {0};
int quickAry[ARRAY_SIZE] = {0};
int start = 0;
int end = 0;
double difference = 0;
int size = ARRAY_SIZE;
srand(time(NULL));
for (int i = 0; i < ARRAY_SIZE; i++) {
masterAry[i] = rand();
}
for (int a = 0; a < ARRAY_SIZE; a++) {
quickAry[a] = masterAry[a];
}
start = clock();
qui = quickSort(quickAry, 0, ARRAY_SIZE - 1);
end = clock();
difference = end - start;
double f = difference / CLOCKS_PER_SEC;
cout << "Quick: " << f << " " << qui.swaps << " " << qui.comps << endl;
}
This is the main. It's where values are assigned to the array to be sorted by the quickSort function, which will be defined below.
int partition(int numbers[], int i, int k) { //add parameters int& swap and int& comp
int l = 0;
int h = 0;
int midpoint = 0;
int pivot = 0;
int temp = 0;
bool done = false;
// Pick middle element as pivot
midpoint = i + (k - i) / 2;
pivot = numbers[midpoint];
l = i;
h = k;
while (!done) {
// Increment l while numbers[l] < pivot
while (numbers[l] < pivot) {
++l;
totalComps++;
}
// Decrement h while pivot < numbers[h]
while (pivot < numbers[h]) {
--h;
totalComps++;
}
// If there are zero or one elements remaining,
// all numbers are partitioned. Return h
if (l >= h) {
totalComps++;
done = true;
}
else {
// Swap numbers[l] and numbers[h],
// update l and h
temp = numbers[l];
numbers[l] = numbers[h];
numbers[h] = temp;
totalSwaps++;
++l;
--h;
}
}
//cout << totalSwaps << " " << totalComps << endl;
return h;
}
This is the partition function to find where to find the next partition point
SwapandComp quickSort(int numbers[], int i, int k) { //add parameters int& swap and int& comp
SwapandComp quick = { 0 };
//quick.swaps = quick.comps = 0;
int j = 0;
int z = 0;
// Base case: If there are 1 or zero elements to sort,
// partition is already sorted
if (i >= k) {
return quick;
}
// Partition the data within the array. Value j returned
// from partitioning is location of last element in low partition.
j = partition(numbers, i, k);
// Recursively sort low partition (i to j) and
// high partition (j + 1 to k)
quickSort(numbers, i, j);
quickSort(numbers, j + 1, k);
quick.swaps = totalSwaps;
quick.comps = totalComps;
//totalSwaps = 0;
//totalComps = 0;
return quick;
}
And finally, here is the quick sort function where all the swaps and comps will be added together and put into the struct. Again, I'm not too sure how to add in the pass by reference variables for swap and comp. Any help is appreciated! (Also sorry about the code formatting, it got kind of crazy on my screen.)

quicksort, helper class problems, timesort, vector, c++

my biggest problem is getting the quickSortHelper class to work. i know what i want the parameters to be, and the stuff inside i need to call on is what i can't figure out. i've tried a mixture of using the partition and quicksort but i can't figure it out. the code is written like this because i will be using a timesort class in the future to solve and time 6+ sorting algorithms. i got it to work by just throwing the code inside main. but all i want inside main is what i have here.
#include <iostream>
#include <algorithm>
#include <vector>
#include <chrono>
#include <functional>
#include <random>
//i know not all the above libraries are being used, once quickSort is
//working i plan on adding it to 5 other sorting algorithms, where these
//are neccessary.
using namespace std;
void quickSort(vector<int>&, int, int);
int partition(vector<int>&, int, int);
double timeSort(vector<int> &v, function<void(vector<int>&)>f);
int main()
{
vector<int>intVec(1000);
generate(intVec.begin(), intVec.end(), rand);
int p = 0;
int q = 1000;
quickSort(intVec, p, q);
auto time = timeSort(intVec, quickSort);
for (auto i = 0u; i != intVec.size(); ++i)
cout << intVec[i] << " ";
cout << "\nQuick sort took " << time << " nanoseconds\n";
char chubby;
cin >> chubby;
return 0;
}
double timeSort(vector<int> &v, function<void(vector<int>&)>f)
{
auto start = chrono::high_resolution_clock::now();
f(v);
auto end = chrono::high_resolution_clock::now();
return static_cast<double>(((end - start).count()));
}
int partition(vector<int>&intVec, int p, int q)
{
int x = intVec[p];
int i = p;
int j;
for (j = p + 1; j < q; j++)
{
if (intVec[j] <= x)
{
i = i + 1;
swap(intVec[i], intVec[j]);
}
}
swap(intVec[i], intVec[p]);
return i;
}
void quickSort(vector<int>&intVec, int p, int q)
{
int r;
if (p < q)
{
r = partition(intVec, p, q);
quickSort(intVec, p, r);
quickSort(intVec, r + 1, q);
}
}
void quickSortHelper(vector<int>&intVec)
{
//i want to make a call to the timeSort function with
//quickSortHelper, i can't use quickSort directly because timeSort
//only has 2 parameters, the vector to be solved, and the method of
//solving it. i know
}
I suggest simplifying your program:
int main(void)
{
vector<int>intVec(1000);
unsigned int duration = 0;
for (unsigned int iteration = 0;
iteration < 1000000;
++iteration)
{
generate(intVec.begin(), intVec.end(), rand);
int p = 0;
int q = 1000;
auto start = chrono::high_resolution_clock::now();
quickSort(intVec, p, q);
auto end = chrono::high_resolution_clock::now();
duration += (end - start);
}
cout << "Average time for quicksort: " << (duration / 1000000) << "\n";
cout.flush();
return 0;
}
I made the following changes:
1) Running the sort for many iterations to get an average duration.
2) Removed the timing function; it only complicates things.
Umm... If I understand correctly, this should do it:
void quickSortHelper(vector<int>&intVec)
{
quickSort(intVec, 0, intVec.size());
}

My C++ simulator crashes the terminal

My code crashes the terminal each time I execute it. I have tried it with Geany and Visual C++ for debugging and it also crashes when just going through cmd prompt.
I got rid of all the bugs using the debugger, but it didn't help. I am supposed to be creating a simulator of a cache, and looking for hits and misses using random numbers, here is my code:
#include <iostream>
#include <cmath>
#include <stdlib.h>
#include <ctime>
#include <iomanip>
#include <fstream>
using namespace std;
const int r = 8192;
const int c = 3;
const int r1 = 262144;
int i;
int j;
int k;
int max;
int min;
int numberW0;
int index_max;
int index_min;
int numberX0;
int tag_max;
int tag_min;
int numberY0;
unsigned int data_max;
int data_min;
int numberZ0;
int numberW1;
int index_max1;
int index_min1;
int numberX1;
int tag_max1;
int tag_min1;
int numberY1;
unsigned int data_max1;
int data_min1;
int numberZ1;
int numberW2;
int index_max2;
int index_min2;
int numberX2;
int tag_max2;
int tag_min2;
int numberY2;
unsigned int data_max2;
int data_min2;
int numberZ2;
int numberW3;
int index_max3;
int index_min3;
int numberX3;
int tag_max3;
int tag_min3;
int numberY3;
unsigned int data_max3;
int data_min3;
int numberZ3;
int numberW4;
int index_max4;
int index_min4;
int numberX4;
int tag_max4;
int tag_min4;
int numberY4;
unsigned int data_max4;
int data_min4;
int numberZ4;
double new_valid = 0;
double new_tag = -9999999999;
double new_data = -9999999999;
double tag_value;
int s;
int t;
double block0;
double block1;
double block2;
double block3;
int v;
double levBlock;
fstream armRes;
int main()
{
double way0 [r][c]; //declaration of the arrays
double way1 [r][c];
double way2 [r][c];
double way3 [r][c];
double lev2[r1][c];
for (i = 0; i < r; i++) // initialization of the arrays
{
way0[i][0] = new_valid;
way0[i][1] = new_tag;
way0[i][2] = new_data;
way1[i][0] = new_valid;
way1[i][1] = new_tag;
way1[i][2] = new_data;
way2[i][0] = new_valid;
way2[i][1] = new_tag;
way2[i][2] = new_data;
way3[i][0] = new_valid;
way3[i][1] = new_tag;
way3[i][2] = new_data;
}
for (j = 0; j < r1; j++)
{
lev2[j][0] = new_valid;
lev2[j][1] = new_tag;
lev2[j][2] = new_data;
}
srand (time(0)); // random number generator seed
int max = r;
int min = 0;
int max1 = r1;
int min1 = 0;
int numberW0 = (rand()%max+min+1); // number of entires to populate way0
for (k = 0; k <= numberW0; k++)
{
int index_max = 8192;
int index_min = 0;
numberX0 = rand()%index_max+index_min+1; // random index to use
int tag_max = 32768;
int tag_min = 0;
numberY0 = rand()%tag_max+tag_min+1; // random tag for the index
unsigned int data_max = 429496729; // random data for the index
int data_min = 0;
numberZ0 = rand()%data_max+data_min+1;
way0 [numberX0][0] = 1;
way0 [numberX0][1] = numberY0;
way0 [numberX0][2] = numberZ0;
}
int numberW1 = (rand()%max+min+1); // number of entires to populate way1
for (k = 0; k <= numberW1; k++)
{
int index_max1 = 8192;
int index_min1 = 0;
numberX1 = rand()%index_max1+index_min1+1; // random index to use
int tag_max1 = 32768;
int tag_min1 = 0;
numberY1 = rand()%tag_max1+tag_min1+1; // random tag for the index
unsigned int data_max1 = 429496729; // random data for the index
int data_min1 = 0;
numberZ1 = rand()%data_max1+data_min1+1;
way1 [numberX1][0] = 1;
way1 [numberX1][1] = numberY1;
way1 [numberX1][2] = numberZ1;
}
int numberW2 = (rand()%max+min+1); // number of entires to populate way2
for (k = 0; k <= numberW2; k++)
{
int index_max2 = 8192;
int index_min2 = 0;
numberX2 = rand()%index_max2+index_min2+1; // random index to use
int tag_max2 = 32768;
int tag_min2 = 0;
numberY2 = rand()%tag_max2+tag_min2+1; // random tag for the index
unsigned int data_max2 = 429496729; // random data for the index
int data_min2 = 0;
numberZ2 = rand()%data_max2+data_min2+1;
way2 [numberX2][0] = 1;
way2 [numberX2][1] = numberY2;
way2 [numberX2][2] = numberZ2;
}
int numberW3 = (rand()%max+min+1); // number of entires to populate way3
for (k = 0; k <= numberW3; k++)
{
int index_max3 = 8192;
int index_min3 = 0;
numberX3 = rand()%index_max3+index_min3+1; // random index to use
int tag_max3 = 32768;
int tag_min3 = 0;
numberY3 = rand()%tag_max3+tag_min3+1; // random tag for the index
unsigned int data_max3 = 429496729; // random data for the index
int data_min3 = 0;
numberZ3 = rand()%data_max3+data_min3+1;
way3 [numberX3][0] = 1;
way3 [numberX3][1] = numberY3;
way3 [numberX3][2] = numberZ3;
}
int numberW4 = (rand()%max1+min1+1); // number of entires to populate level 2
for (k = 0; k <= numberW4; k++)
{
int index_max4 = r1;
int index_min4 = 0;
numberX4 = rand()%index_max4+index_min4+1; // random index to use
int tag_max4 = 32768;
int tag_min4 = 0;
numberY4 = rand()%tag_max4+tag_min4+1; // random tag for the index
unsigned int data_max4 = 429496729; // random data for the index
int data_min4 = 0;
numberZ4 = rand()%data_max4+data_min4+1;
lev2 [numberX4][0] = 1;
lev2 [numberX4][1] = numberY4;
lev2 [numberX4][2] = numberZ4;
}
armRes.open("C:\\Users\\Max\\Documents\\CSIT4\\Project\\Practice\\ARMresults.txt", ios::out | ios::app );
for (t = 0; t<= 15000; t++)
{
int tag_value = rand()%32768+0+1;
for (s = 0; s <= r; s++)
{
block0 = way0 [s][1];
block1 = way1 [s][1];
block2 = way2 [s][1];
block3 = way3 [s][1];
if (tag_value == block0)
{
armRes << "L1 Hit (Way 0) -- AT INDEX: " << s << endl;
}
else if (tag_value == block1)
{
armRes << "L1 Hit (Way1) -- AT INDEX: " << s << endl;
}
else if (tag_value == block2)
{
armRes << "L1 Hit (Way2) -- AT INDEX: " << s << endl;
}
else if (tag_value == block3)
{
armRes << "L1 Hit (Way3) -- AT INDEX: " << s << endl;
}
else
{
for (v = 0; v <= r1; v++)
{
double levBlock = lev2 [v][1];
if (tag_value == levBlock)
{
armRes << "L2 Hit -- AT INDEX: " << v << endl;
}
else
{
armRes << "Cache Miss For Tag: " << tag_value << endl;
}
}
}
}
}
armRes.close();
return 0;
}
Any help would be greatly appreciated as I no longer have any academic help
One issue right away: You are more than likely blowing out the stack with the memory taken up by those arrays in main(). Since you're using Visual C++, I can assume the following:
double way0 [r][c]; //declaration of the arrays
double way1 [r][c];
double way2 [r][c];
double way3 [r][c];
double lev2[r1][c];
Given this:
const int r = 8192;
const int c = 3;
const int r1 = 262144;
If the sizeof(double) == 8, then that is over 7,000,000 bytes of stack required to hold those arrays. The default stack is (I believe) 1 megabyte (maybe 2 megabytes, can't recall off the top of my head), but nowhere near close to 7 megabytes.
Therefore you need to use dynamic allocation to create those arrays. The simplest way is to use a std::vector and size accordingly.
#include <vector>
//...
typedef std::vector<double> Double1D;
typedef std::vector<Double1D> Double2D;
Double2D way0(r, Double1D(c));
Double2D way1(r, Double1D(c));
Double2D way2(r, Double1D(c));
Double2D way3(r, Double1D(c));
Double2D lev2(r1, Double1D(c));
This now creates the data away from the stack and instead onto the heap. The rest of the code should be able to compile with no further changes.
Note that I did not check any of the array indices you're using in the rest of your program, so you could still have an array access violation somewhere in the rest of the code. Others have commented that you do have some index boundary issues using rand(), but at least you won't run into stack space issues.