在C++获得"corrupted size vs. prev_size"



我正试图创建一个程序,在从文件中读取数据后打印2D矩阵。

如果2D矩阵是一个X&Y值,但我得到";损坏的大小相对于prev_ size";如果它是一个矩形,例如x=8和y=10,则出错。

下面是一个成功运行的示例(其中x是8,y是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   

当我尝试使用一个x是8,y是10的配置文件时,我会得到这样的错误:

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)

这就是我的代码:

#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;
}

我怀疑问题在于读取其他文件并用其数据(城市、云、压力文件(填充2D阵列,但我似乎不明白哪里出了问题。

我试着注释processConfigFile的底部,只是想看看2D阵列是否在没有向每个瓦片插入任何信息的情况下正确创建,尽管对齐有点混乱,但它还是有效的(其中x是8,y是10(:

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

我没有包括用于读取其他文件的代码,因为它基本上是一样的,只是做了一些小的调整。

如有任何帮助,我们将不胜感激!

好吧,让我们来解决这个显而易见的错误。我敢打赌,这并不是这个程序的唯一问题,因为仔细查看它,我会发现对内存、指针使用和对象生存期的误解不断。

不管怎样,就在这里:

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

请注意,您分配了一个可以容纳gridSize.gridXHighestVal + 1值的指针数组,但随后使用gridSize.gridYHighestVal + 1值填充该数组。如果维度不是正方形的,那么你要么会分配太少的子数组,要么会溢出缓冲区并将指针写入你没有业务写入的内存

因此,循环应该是:

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

最新更新