在 C++ 中获取 "corrupted size vs. prev_size"
Getting "corrupted size vs. prev_size" in C++
我正在尝试创建一个程序来在从文件中读取数据后打印二维矩阵。
如果 2D 矩阵是 X 和 Y 值相等的正方形,我的程序运行良好,但如果它是矩形,例如 x=8,我会收到“损坏的大小与 prev_size”错误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;
}
我怀疑问题在于读取其他文件并用其数据(城市、云、压力文件)填充二维数组,但我似乎无法理解哪里出错了。
我尝试注释掉 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
值填充了该数组。如果尺寸不是正方形,那么您要么分配太少 sub-arrays,要么溢出缓冲区并将指针写入您没有业务写入的内存。
所以循环应该是:
for (int i = 0; i < gridSize.gridXHighestVal + 1; i++)
我正在尝试创建一个程序来在从文件中读取数据后打印二维矩阵。
如果 2D 矩阵是 X 和 Y 值相等的正方形,我的程序运行良好,但如果它是矩形,例如 x=8,我会收到“损坏的大小与 prev_size”错误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;
}
我怀疑问题在于读取其他文件并用其数据(城市、云、压力文件)填充二维数组,但我似乎无法理解哪里出错了。
我尝试注释掉 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
值填充了该数组。如果尺寸不是正方形,那么您要么分配太少 sub-arrays,要么溢出缓冲区并将指针写入您没有业务写入的内存。
所以循环应该是:
for (int i = 0; i < gridSize.gridXHighestVal + 1; i++)