Home > OS >  Getting "corrupted size vs. prev_size" in C
Getting "corrupted size vs. prev_size" in C

Time:02-10

I'm trying to create a program to print a 2D matrix after reading in data from a file.

My program works fine if the 2D matrix is a square with equal X & Y values, but I get the "corrupted size vs. prev_size" error if its a rectangle, for example with x=8 and y=10.

Here is an example of what it should look like if run successfully (where x is 8 and y is 8):

  # # # # # # # # # # # 
8 #     2 2           # 
7 #     2 2       1   # 
6 #                   # 
5 #                   # 
4 #                   # 
3 #   3 3 3           # 
2 #   3 3 3           # 
1 #   3 3 3           # 
0 #                   # 
  # # # # # # # # # # # 
    0 1 2 3 4 5 6 7 8   

When I try to use a configuration file where x is 8 and y is 10 I get the error as such:

Please enter your choice : 1

[ Read in and process a configuration file ]
Please enter config filename : TestCases_Config.txt

Reading in GridX_IdxRange : GridX_IdxRange=0-8 ... done!
Reading in GridY_IdxRange : GridY_IdxRange=0-10 ... done!

Storing data from input file :
*** Error in `./csci251_a1.exe': corrupted size vs. prev_size: 0x08e63d40 ***
Aborted (core dumped)

This is what my code looks like:

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm> // To use unique function
#include <iomanip> // For setprecision
#include <vector> // To use vectors

using namespace std;

// Struct to store the maximum grid values from config file
struct gridSize
{
    int gridXHighestVal;
    int gridYHighestVal;

    string toString();
};

// Struct object to store individual grid tile details
struct gridTileDetails
{
    int x, y;
    bool isOccupied;
    int cityID;
    string cityName;
    int cloudIndex, singleCloudIndex, pressureIndex, singlePressureIndex;
    char cloudLMH, pressureLMH;

    string toString();
};

gridSize gridSize; // Global gridSize struct to be used to obtain maximum X & Y values
gridTileDetails **grid; // Global pointer-to-pointer variable to be used for dynamically allocating 2D array

// All function/method prototypes
// Functions for reading of data (Menu option #1)
gridTileDetails processConfigFile();
gridTileDetails readCityFile(string);
gridTileDetails readCloudFile(string);
gridTileDetails readPressureFile(string);

// Functions for menu options #2 - #7
void displayCityMap(int, int);
void displayCloudMap(int, int);
void displayCloudMapLMH(int, int);
void displayPressureMap(int, int);
void displayPressureMapLMH(int, int);
void generateWeatherReport(int, int);

// Helper functions
void safelyDeallocateMemory (int arrayCols, gridTileDetails **grid);
vector<string> tokenizeString(string, string);
vector<int> removeDuplicates(vector<int> &vec);
char getLMH(int);
int printCity(int, int, vector<int> , int);
double calculateRain(char, char);
void printRain(double);

int main() 
{
    
    int userChoice;

    // Main menu to run constantly until user enters 8
    while (userChoice != 8) 
    {
        cout << "Welcome to Weather Information Processing System!" << endl;

        cout << endl;

        cout << "1)\tRead in and process a configuration file" << endl;
        cout << "2)\tDisplay city map" << endl;
        cout << "3)\tDisplay cloud coverage map (cloudiness index)" << endl;
        cout << "4)\tDisplay cloud coverage map (LMH symbols)" << endl;
        cout << "5)\tDisplay atmospheric pressure map (pressure index)" << endl;
        cout << "6)\tDisplay atmospheric pressure map (LMH symbols)" << endl;
        cout << "7)\tShow forecast summary report" << endl;
        cout << "8)\tQuit" << endl;

        cout << endl;

        cout << "Please enter your choice : ";
        cin >> userChoice;

        cout << endl;

        switch (userChoice) 
        {
            case 1:
                // Process configuration file
                **grid = processConfigFile();
                break;
            case 2:
                // Display city map
                displayCityMap(gridSize.gridXHighestVal, gridSize.gridYHighestVal);
                break;
            case 3:
                // Display cloud coverage map (cloudiness index)
                displayCloudMap(gridSize.gridXHighestVal, gridSize.gridYHighestVal);
                break;
            case 4:
                // Display cloud coverage map (LMH symbols)
                displayCloudMapLMH(gridSize.gridXHighestVal, gridSize.gridYHighestVal);
                break;
            case 5:
                // Display atmospheric pressure map (pressure index)
                displayPressureMap(gridSize.gridXHighestVal, gridSize.gridYHighestVal);
                break;
            case 6:
                // Display atmospheric pressure map (LMH symbols)
                displayPressureMapLMH(gridSize.gridXHighestVal, gridSize.gridYHighestVal);
                break;
            case 7:
                // Show weather forecast summary report
                generateWeatherReport(gridSize.gridXHighestVal, gridSize.gridYHighestVal);
                break;
            case 8:
                // Message to be shown for quiting program
                cout << "Thank you for using the Weather Information Processing System!" << endl;
                break;
            default:
                cout << "Please enter a valid input!" << endl << endl;
        }
    }
    
    safelyDeallocateMemory (gridSize.gridXHighestVal, grid);

    return (0);
}

// Begin reading of files
gridTileDetails processConfigFile() 
{
    string filename;

    cout << "[ Read in and process a configuration file ]" << endl;
    cout << "Please enter config filename : ";
    cin >> filename;

    cout << endl;

    // Create fstream object
    fstream input_file(filename.c_str(), fstream::in);

    string aline;
    string gridX = "GridX_IdxRange";
    string gridY = "GridY_IdxRange";

    while (getline(input_file, aline)) // With input_file as the source, store each "line" into our string variable aline;
    {

        if (aline.find(gridX) != string::npos) // If "GridX_IdxRange" is found within aline
        {
            string numString = aline.substr(15); // Obtain only the number range portion of string

            vector<string> individualNums = tokenizeString(numString, "-"); // Use "-" as delimiter to obtain individual numbers
            
            int gridX = stoi(individualNums[1]); // Convert string to an int variable       
            
            gridSize.gridXHighestVal = gridX; // Store grid X maximum value into custom struct object

            cout << "Reading in GridX_IdxRange : " << aline << " ... done!" << endl;
            individualNums.clear();
        }

        if (aline.find(gridY) != string::npos) // If "GridY_IdxRange" is found within aline
        {

            string numString = aline.substr(15); // Obtain only the number range portion of string

            vector<string> individualNums = tokenizeString(numString, "-"); // Use "-" as delimiter to obtain individual numbers

            int gridY = stoi(individualNums[1]); // Convert string to an int variable

            gridSize.gridYHighestVal = gridY; // Store grid Y maximum value into custom struct object

            cout << "Reading in GridY_IdxRange : " << aline << " ... done!" << endl;
            individualNums.clear();
        }
        
        if (gridSize.gridXHighestVal != 0 && gridSize.gridYHighestVal != 0) // Break out of the while-loop if both X & Y values are populated, to continue processing
        {
            break;
        }
    }

    cout << endl;

    // Dynamic memory allocation for 2D array
    grid = new gridTileDetails * [gridSize.gridXHighestVal   1];
    for (int i = 0; i < gridSize.gridYHighestVal   1; i  )
    {
        grid[i] = new gridTileDetails[gridSize.gridYHighestVal   1];
    }

    // Putting x (columns) and y (rows) values into 2D array
    for (int col = 0; col < gridSize.gridXHighestVal   1; col  ) 
    {
        for (int row = 0; row < gridSize.gridYHighestVal   1; row  ) 
        {
            grid[col][row].x = col;
            grid[col][row].y = row;
        }
    }
    
    
    int fileCounter = 0; // File counter variable to decide which file method to use
    cout << "Storing data from input file :" << endl;

    while (getline(input_file, aline)) 
    {

        if (aline.find(".txt") != string::npos) // If aline contains ".txt" at the end, we know it is one of the configuration files
        {
            
            switch (fileCounter)
            {
                case 0: // Get city details
                    **grid = readCityFile(aline);
                    cout << aline << " ... done!" << endl;
                    break;
                case 1: // Get cloud details
                    **grid = readCloudFile(aline);
                    cout << aline << " ... done!" << endl;
                    break;
                case 2: // Get pressure details
                    **grid = readPressureFile(aline);
                    cout << aline << " ... done!" << endl;
                    break;
            }
            fileCounter  ;
        }
        
    }
    cout << endl;

    cout << "All records successfully stored. Going back to main menu ..." << endl;

    cout << endl;
    
    return **grid;
}

// Method for reading city file
gridTileDetails readCityFile(string filename) 
{
    
    // Create fstream object
    fstream input_file(filename.c_str(), fstream::in);

    string aline;

    while (getline(input_file, aline)) 
    {
        if (aline == "")
        {
            break;
        }

        vector<string> allConfigInfo = tokenizeString(aline, "-"); // Separates all data with delimiter "-" Eg. [1,1] 3 Big_City

        string gridString = allConfigInfo[0]; // Gets part of vector storing grid info
        string cityID = allConfigInfo[1];
        string cityName = allConfigInfo[2];
        
        gridString = gridString.substr(1, gridString.size() - 2); // Removes [ and ] brackets
        
        vector<string> gridValues = tokenizeString(gridString, ", "); // Get individual grid values

        // Get grid values
        int gridX = stoi(gridValues[0]);
        int gridY = stoi(gridValues[1]);
        
        // Get city ID
        int intCityID = stoi(cityID);

        // Inserting values into 2D array
        grid[gridX][gridY].cityID = intCityID;
        grid[gridX][gridY].isOccupied = true;
        grid[gridX][gridY].cityName = cityName;

    }
    return **grid;
}

I suspect the issues lies with the reading of the other files and populating the 2D array with its data (city, cloud, pressure files) but I can't seem to understand where I went wrong.

I tried commenting out the bottom portion of processConfigFile just to see if the 2D array gets created correctly without inserting any information to each tile and although the alignment got messed up a little, it worked (where x is 8 and y is 10):

  # # # # # # # # # # # 
10 #                   # 
9 #                   # 
8 #                   # 
7 #                   # 
6 #                   # 
5 #                   # 
4 #                   # 
3 #                   # 
2 #                   # 
1 #                   # 
0 #                   # 
  # # # # # # # # # # # 
    0 1 2 3 4 5 6 7 8   

I didn't include the code for the reading of the other files as its mostly the same, just with some minor adjustments.

Any help provided would be greatly appreciated!

CodePudding user response:

Well, let's just address the glaringly obvious mistake. I'll bet this is not the only problem with this program, because looking through it I see repeated misunderstanding of memory, pointer use and object lifetime.

Anyway, right here you have:

grid = new gridTileDetails * [gridSize.gridXHighestVal   1];
for (int i = 0; i < gridSize.gridYHighestVal   1; i  )
{
    grid[i] = new gridTileDetails[gridSize.gridYHighestVal   1];
}

Notice that you allocated an array of pointers that can hold gridSize.gridXHighestVal 1 values, but you then populate that array with gridSize.gridYHighestVal 1 values. If the dimensions are not square, then you'll either allocate too few sub-arrays, or you'll overrun the buffer and write pointers into memory you have no business writing to.

So the loop should instead be:

for (int i = 0; i < gridSize.gridXHighestVal   1; i  )
  • Related