-4

Okay, so I created some throws for my safeArray::operator[], but the throws only work for certain numbers -- the other numbers cause the program to crash for some reason.

At the moment if I have:

if (index < startingIndex)
    {
        try
        {
            throw 1;

        }
        catch (int &e)
        {
            printf("caught it\n"); throw;
        }
    }

The throws work as intended and don't crash my program, but if I include:

if (index >= capacity)
    {
        try
        {
            throw 1;

        }
        catch (int &e)
        {
            printf("caught it\n"); throw;
        }
    }

When I include this bit of code to add throws to the rest of the numbers then my program crashes and says abort() has been called. As far as I can tell the parameters are correct so I'm not sure why its crashing.

The rest of the code:

#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>

//To prevent those using g++ from trying to use a library
//they don't have
#ifndef __GNUC__
#include <conio.h>
#endif

using namespace std;

class SafeArray {


public:
    SafeArray();
    SafeArray(const int, const unsigned int);
    ~SafeArray();
    int& operator[](const int);
    friend string arrayToString(const SafeArray&);
    int getLowIndex();
    int getHighIndex();
    int length();
    void resize(const int, const unsigned int);


private:
    unsigned int capacity;
    int * arr;
    int startingIndex;
};

int SafeArray::getHighIndex(){
    int low = this->startingIndex;
    int high = this->capacity;
    int retval = low + high - 1;
    return retval;
}

int SafeArray::getLowIndex() {

    return startingIndex;
}

int SafeArray::length() {

    return capacity;
}

void SafeArray::resize(const int start, const unsigned int capacity1)
{
    int delta = startingIndex - start;
    size_t newSize = capacity1;
    int* newArr = new int[newSize];

    memcpy(newArr+delta, arr, capacity * sizeof(int));

    capacity = newSize;
    delete[] arr;
    this->startingIndex = start;
    this->capacity = capacity1;
    arr = newArr;
}



//This helps with testing, do not modify.
bool checkTest(string testName, string whatItShouldBe, string whatItIs) {

    if (whatItShouldBe == whatItIs) {
        cout << "Passed " << testName << endl;
        return true;
    }
    else {
        cout << "****** Failed test " << testName << " ****** " << endl << "     Object contained: " << whatItIs << endl << "     Output should have contained: " << whatItShouldBe << endl;
        return false;
    }
}

//This helps with testing, do not modify.
bool checkTest(string testName, int whatItShouldBe, int whatItIs) {

    if (whatItShouldBe == whatItIs) {
        cout << "Passed " << testName << endl;
        return true;
    }
    else {
        cout << "****** Failed test " << testName << " ****** " << endl << "     Object contained: " << whatItIs << endl << "     Output should have contained: " << whatItShouldBe << endl;
        return false;
    }
}

string arrayToString(const SafeArray& obj) {
    stringstream ss;

    for (unsigned int i = 0; i < obj.capacity; i++) {
        ss << obj.arr[i] << " ";
    };
    string str = ss.str();
    size_t found;
    found = str.find_last_not_of(" ");
    if (found != string::npos)
        str.erase(found + 1);
    else
        str.clear();            // str is all whitespace

    return str;
}

SafeArray::SafeArray(const int startingIndex, const unsigned int capacity) {
    this->arr = new int[capacity];   

    this->startingIndex = startingIndex;

    this->capacity = capacity;

}

SafeArray::~SafeArray() {
    delete[] arr;
}

int& SafeArray::operator[](int index) {
    if (index < startingIndex)
    {
        try
        {
            throw 1;

        }
        catch (int &e)
        {
            printf("caught it\n"); throw;
        }
    }


    return arr[index-startingIndex];
}

void safeArrayTests() {

    //Test constructor
    SafeArray a(0, 5);
    for (int i = 0; i < 5; i++) {
        a[i] = i + 20;
    };

    checkTest("safeArrayTests #1", "20 21 22 23 24", arrayToString(a));
    //Test methods
    checkTest("safeArrayTests #2", 0, a.getLowIndex());
    checkTest("safeArrayTests #3", 4, a.getHighIndex());
    checkTest("safeArrayTests #4", 5, a.length());
    //Test operator [] overload
    checkTest("safeArrayTests #5", 20, a[0]);
    checkTest("safeArrayTests #6", 24, a[4]);
    try {
        checkTest("safeArrayTests #7", 0, a[5]);
        cout << "Passed safeArayTests #7" << endl;
    }
    catch (int error) {
        cout << "Passed safeArayTests #7" << endl;
    }
    try {
        checkTest("safeArrayTests #8", 0, a[-1]);
        cout << "****** Failed test safeArayTests #8 ******.  An error should have been thrown, but wasn't." << endl;
    }
    catch (int error) {
        cout << "Passed safeArayTests #8" << endl;
    }

    //Test offsetting the array
    SafeArray b(5, 10);
    int i;
    for (i = 5; i < 15; i++) {
        b[i] = i + 100;
    };

    checkTest("safeArrayTests #9", "105 106 107 108 109 110 111 112 113 114", arrayToString(b));
    //Test methods
    checkTest("safeArrayTests #10", 5, b.getLowIndex());
    checkTest("safeArrayTests #11", 14, b.getHighIndex());
    checkTest("safeArrayTests #12", 10, b.length());
    //Test operator [] overload
    checkTest("safeArrayTests #13", 105, b[5]);
    checkTest("safeArrayTests #14", 114, b[14]);
    try {
        checkTest("safeArrayTests #15", 0, b[4]);
        cout << "****** Failed test safeArayTests #7 ******.  An error should have been thrown, but wasn't." << endl;
    }
    catch (int error) {
        cout << "Passed safeArayTests #15" << endl;
    }
    try {
        checkTest("safeArrayTests #16", 0, a[15]);
        cout << "****** Failed test safeArayTests #7 ******.  An error should have been thrown, but wasn't." << endl;
    }
    catch (int error) {
        cout << "Passed safeArayTests #16" << endl;
    }

    //Test resizing
    //Make sure the existing elements were untouched.
    b.resize(3, 15);
    checkTest("safeArrayTests #17", 3, b.getLowIndex());
    checkTest("safeArrayTests #18", 17, b.getHighIndex());
    checkTest("safeArrayTests #19", 15, b.length());
    checkTest("safeArrayTests #20", 105, b[5]);
    checkTest("safeArrayTests #21", 114, b[14]);
    //attempt to write to b[3] and b[17] without crashing
    b[3] = 1;
    b[17] = 2;
    checkTest("safeArrayTests #22", 1, b[3]);
    checkTest("safeArrayTests #23", 2, b[17]);
    try {
        b[2] = 666;
        cout << "****** Failed test safeArayTests #24 ******.  An error should have been thrown, but wasn't." << endl;
    }
    catch (int error) {
        cout << "Passed safeArayTests #24" << endl;
    }



    //Test resizing into negative
    b.resize(-4, 23);
    checkTest("safeArrayTests #25", 105, b[5]);
    checkTest("safeArrayTests #26", 114, b[14]);
    checkTest("safeArrayTests #27", 1, b[3]);
    checkTest("safeArrayTests #28", 2, b[17]);
    b[-4] = 1234;
    checkTest("safeArrayTests #29", 1234, b[-4]);


    //Test offsetting the array
    SafeArray c(-20, 4);
    for (i = -20; i < -16; i++) {
        c[i] = i - 10;
    };

    checkTest("safeArrayTests #30", "-30 -29 -28 -27", arrayToString(c));
    //Test methods
    checkTest("safeArrayTests #31", -20, c.getLowIndex());
    checkTest("safeArrayTests #32", -17, c.getHighIndex());
    checkTest("safeArrayTests #33", 4, c.length());
    //Test operator [] overload
    checkTest("safeArrayTests #34", -30, c[-20]);
    checkTest("safeArrayTests #35", -27, c[-17]);

    //Test resizing
    //Make sure the existing elements were untouched.
    c.resize(-21, 6);
    checkTest("safeArrayTests #36", -21, c.getLowIndex());
    checkTest("safeArrayTests #37", -16, c.getHighIndex());
    checkTest("safeArrayTests #38", 6, c.length());
    checkTest("safeArrayTests #39", -30, c[-20]);
    checkTest("safeArrayTests #40", -27, c[-17]);
    //attempt to write to c[-21] and c[-16] without crashing
    c[-21] = 1;
    c[-16] = 2;
    checkTest("safeArrayTests #41", 1, c[-21]);
    checkTest("safeArrayTests #42", 2, c[-16]);


    //Test an array of one element
    SafeArray d(3, 1);
    d[3] = 1111;

    checkTest("safeArrayTests #43", "1111", arrayToString(d));
    //Test methods
    checkTest("safeArrayTests #44", 3, d.getLowIndex());
    checkTest("safeArrayTests #45", 3, d.getHighIndex());
    checkTest("safeArrayTests #46", 1, d.length());
    //Test operator [] overload
    checkTest("safeArrayTests #47", 1111, d[3]);

    //Test resizing
    //Make sure the existing elements were untouched.
    d.resize(2, 2);
    checkTest("safeArrayTests #48", 2, d.getLowIndex());
    checkTest("safeArrayTests #49", 3, d.getHighIndex());
    checkTest("safeArrayTests #50", 2, d.length());
    checkTest("safeArrayTests #51", 1111, d[3]);
    //attempt to write to d[2] without crashing
    d[2] = 2222;
    checkTest("safeArrayTests #52", 2222, d[2]);



}

int main() {
    safeArrayTests();
#ifndef __GNUC__
    cout << "Press any key to continue" << endl;
    _getch();
#endif
}

The solution: The solution: if (index > SafeArray::getHighIndex()) { throw 1; }

Trevor
  • 7
  • 3
  • 2
    You were already told in your previous question that there's no point in throwing and catching like this. You're just introducing an unnecessary complication. – juanchopanza Oct 26 '15 at 07:01
  • Also, think about it: how do you expect a simple `printf` statement to make your code work when you access the array out of bounds? – juanchopanza Oct 26 '15 at 07:06
  • I've tried several things, but I keep getting the same result. I've omitted the catches entirely and I've also tried others people's methods with the catches but it still crashes – Trevor Oct 26 '15 at 07:06
  • I suggest you read up on how to use exceptions before trying any more things. – juanchopanza Oct 26 '15 at 07:07
  • As far as I can tell though the catches don't seem to be crucial for the program to work – Trevor Oct 26 '15 at 07:07
  • Your example is a long way from being *Minimal* – M.M Oct 26 '15 at 07:26
  • The `resize` function writes out of bounds if the array is being made smaller – M.M Oct 26 '15 at 07:27
  • `if index >= capacity` doesn't seem to appear in the code sample either. Your example needs to actually show the problem. – M.M Oct 26 '15 at 07:29
  • I still don't think I'm even supposed to be using catches for the assignment. I've looked at other programs similar to mine and none of them seem to need elaborate catches. If they do need elaborate catches I wouldn't have the slightest idea how to code one. As far as I can tell from the assignment directions I should be able to get away with just "throw 1;" with no catches whatsoever. I think we are focusing on the wrong thing here. – Trevor Oct 26 '15 at 07:30
  • I took it out of the code I have cause it doesn't do anything. Also, since I can get the first half of the code to worth without catches I don't really see why I'm not able to get the second half to work – Trevor Oct 26 '15 at 07:30
  • It's fine that resize writes out of bounds if being smaller. I am only being asked to make them bigger. – Trevor Oct 26 '15 at 07:32
  • Actually to further prove that I don't need those catches. I can entirely omit any code that would even cause an index out of bounds but the program will still crash if I have the code mentioned above. – Trevor Oct 26 '15 at 07:37

1 Answers1

0

First it seems you have a logical error:

You want to support custom bounds, so if (index >= capacity) is wrong, since you need to consider startingIndex and capacity in order to get the correct upper bound.

Next, I didn't test the effect of comparing int with unsigned int, but you may want to cast capacity to a larger signed type before performing the comparison.

grek40
  • 13,113
  • 1
  • 24
  • 50