// Osman Zakir
// 11 / 10 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 20 "Find highest element" example code (with templated high() function)
// This program has a serious bug that I have to find and fix.
#include "../../cust_std_lib_facilities.h"
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <vld.h>
double *high(double *first, double *last);
double *get_from_jack(int *count);
std::vector<double> *get_from_jill();
void fct();
int main()
{
try
{
fct();
}
catch (const std::exception &e)
{
std::cerr << "Exception: " << e.what() << '\n';
}
keep_window_open();
}
double *high(double *first, double *last)
// return an iterator to the element in [first:last) that has the highest value
{
double h = -1;
double *high;
for (double *p = first; p != last; ++p)
{
if (h < *p)
{
high = p;
h = *p;
}
}
return high;
}
double *get_from_jack(int *count)
{
*count = 45;
double *data_arr = nullptr;
try
{
data_arr = newdouble[*count];
}
catch (const std::bad_alloc &e)
{
std::cout << "Bad allocation error: " << e.what() << '\n';
}
catch (const std::exception &e)
{
std::cout << "Exception: " << e.what() << '\n';
}
std::ifstream ifs{ "velocities1.txt" };
std::size_t i = 0;
for (double velocity; ifs >> velocity;)
{
data_arr[i] = velocity;
++i;
}
return data_arr;
}
std::vector<double> *get_from_jill()
{
std::vector<double> *data_vec = nullptr;
try
{
data_vec = new std::vector<double>;
}
catch (const std::bad_alloc &e)
{
std::cerr << "Bad alloction error: " << e.what() << '\n';
}
std::ifstream ifs{ "velocities2.txt" };
for (double velocity; ifs >> velocity;)
{
data_vec->push_back(velocity);
}
return data_vec;
}
void fct()
{
int jack_count = 0;
double *jack_data = get_from_jack(&jack_count);
std::vector<double> *jill_data = get_from_jill();
//std::sort(jack_data, jack_data + jack_count);
//std::sort(&jill_data->begin(), &jill_data->end());
double *jack_high = high(jack_data, jack_data + jack_count);
std::vector<double> &v = *jill_data;
double *jill_high = high(&v[0], &v[0] + v.size());
std::cout << "Jill's high " << *jill_high << "; Jack's high " << *jack_high << '\n';
delete[] jack_data;
jack_data = nullptr;
delete jill_data;
jill_data = nullptr;
}
It freezes on line 110. But if I comment that line and the one right below it out, I end up with one memory leak. How do I fix this?
There are also two bugs in here I need to find and fix. One I already know of: h = -1 (line 35). I need to find the other one. Apparently, the other one can make it crash.
No attempt is made in get_from_jack to ensure the bounds of the array allocated therein are respected (ignoring the inadequate exception handling.) Also, no attempt is made to ensure that *count refers to the number of values actually read. IIRC, reading the uninitialized elements of that array (if any) will result in undefined behavior.
I should say that I wrote get_from_jill() and get_from_jack() myself and that the rest of the code was provided by the book (except for the commented out calls to sort(), which I put in there just in case I needed to sort the array and vector to make sure that the first element is really the lowest value and that the last element is really the highest value). This is what the book said about it:
We left two potentially serious errors in this little program. One can cause a
crash, and the other will give wrong answers if high() is used in many other
programs where it might have been useful. The general techniques that we
describe below will make them obvious and show how to systematically
avoid them. For now, just find them and suggest remedies.
It talks about STL techniques and about generalizing code after that. And uses iterators and a template in high(). But then leaves another error in the program for the reader to find.
But yeah, since I'm the one who did the exception handling, I'll have to ask for help on that if that's okay.
How do I make sure that *count really refers to the number of elements allocated? I don't think I can have uninitialized elements since I'm using count to allocate the array. So "count" is the size of the array. I just need to do bounds checking. But where do I actually do it?