#c
Вопрос:
Я продолжаю получать ошибки «исключение» и «Необработанное исключение» в последнем цикле for моего кода. Я не уверен, почему это происходит, что это значит и как это исправить. Результат даже не будет отображаться достаточно долго, чтобы я мог убедиться, что он правильный. Любая помощь будет признательна.
Ошибка гласит : Исключение, созданное при 0x00855AC9 в финале Project.exe: 0xC0000005: Место чтения с нарушением доступа 0xCCCCCCCC. Необработанное исключение в 0x00855AC9 в финале Project.exe: 0xC0000005: Место чтения с нарушением доступа 0xCCCCCCCC.
class Geometry {
public:
string color = "blue";
void printColor() {
cout << color << endl;
}
virtual void calArea() {
cout << "Are: 0" << endl;
cout << "Shape: Unknown" << endl;
}
};
class Circle :public Geometry {
private:
double radius;
double area = 0;
public:
Circle() {
radius = 5.0;
}
void calArea() {
area = 3.14 * radius * radius;
cout << "Area: " << ", Shape: Circle, Radius: " << radius << endl;
}
};
class Square :public Geometry {
private:
double side;
double area = 0.0;
public:
Square() {
side = 5.3;
}
void calArea() {
area = side * side;
cout << "Area: " << area << ", Shape: Sqaure, Side: " << side << endl;
}
};
class Cube : public Geometry {
private:
double length;
double width;
double height;
double area;
public:
Cube() {
length = 4.0;
width = 4.0;
height = 4.0;
}
void calArea() {
area = 6 * length * width;
cout << "Area: " << ", Shape: Cube, Length: " << length << ", Width: " << width << ", Height: " << height << endl;
}
};
int main()
{
const int SIZE = 10;
int i;
Geometry* shapes[SIZE];
for ( i = 0; i < SIZE; i ) {
int choice = 1 rand() % 3;
if (choice == 1) {
shapes[i] = new Circle();
}
else if (choice == 2) {
shapes[i] = new Square();
}
else if (choice == 3) {
shapes[i] = new Cube();
}
for (i = 0; i < SIZE; i ) {
shapes[i]->calArea();
}
}
return 0;
}
Комментарии:
1. «Вывод даже не будет отображаться достаточно долго, чтобы я мог убедиться, что он правильный». — Я так понимаю, вы запускаете программу из своей среды разработки? Запуск его с помощью отладчика может быть более информативным. Или запуск его из командной строки, скорее всего, сохранит вывод достаточно долго, чтобы вы могли его прочитать.
2. Я использую visual studio, я думаю, что я работаю с отладчиком, но я не уверен. Я вообще очень новичок в кодировании. Как мне запустить его с помощью отладчика? @JaMiT
3. Если вы запускаете его с отладчиком, должна быть возможность пошагового просмотра программы, чтобы вы могли видеть, где выполнение отличается от ваших ожиданий. (Выполнение приостанавливается на каждой строке.) У вас также должна быть возможность просматривать значения ваших переменных по мере прохождения программы.
4. Когда вы видите какое-то число, которое странно повторяется или выглядит как слово, это обычно программа пытается вам что-то сказать. Посмотрев CCCCCCCC, я нахожу эту страницу , которая предполагает, что это, вероятно, результат неинициализированной автоматической переменной, и, поскольку ошибка является нарушением прав доступа, адрес чтения CCCCCCCC, это, вероятно, неинициализированный указатель.
Ответ №1:
Ваш код получил доступ к неинициализированной памяти, расположение 0xCCCCCCCC
означает неинициализированный указатель в режиме отладки в visual studio
0xCC При компиляции кода с параметром /GZ неинициализированным переменным автоматически присваивается это значение (на уровне байтов).
Я думаю, что»} » нужно поставить перед последним циклом, тогда все указатели в массиве будут введены. И было бы лучше использовать std::vector
здесь, мой окончательный код использует его.
for ( i = 0; i < SIZE; i ) {
int choice = 1 rand() % 3;
if (choice == 1) {
shapes[i] = new Circle();
}
else if (choice == 2) {
shapes[i] = new Square();
}
else if (choice == 3) {
shapes[i] = new Cube();
}
for (i = 0; i < SIZE; i ) {
shapes[i]->calArea();
}
}
Необходимо изменить, чтобы:
for ( i = 0; i < SIZE; i ) {
int choice = 1 rand() % 3;
if (choice == 1) {
shapes[i] = new Circle();
}
else if (choice == 2) {
shapes[i] = new Square();
}
else if (choice == 3) {
shapes[i] = new Cube();
}
}
for (i = 0; i < SIZE; i ) {
shapes[i]->calArea();
}
После исправления в вашем коде все еще есть утечки памяти. Возможно, вы подумаете об использовании здесь интеллектуального указателя. Поскольку мы сохранили указатель базового типа, нам нужен виртуальный деструктор, чтобы убедиться, что память, подлежащая исправлению, удалена.
Для rand()
функции вам нужно вызвать srand
ее перед использованием, чтобы избежать всегда получать одну и ту же случайную последовательность при каждом запуске. И лучше использовать random начиная с c 11.
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using namespace std;
class Geometry {
public:
virtual ~Geometry() = defau<
string color = "blue";
void printColor() { cout << color << endl; }
virtual void calArea() {
cout << "Are: 0" << endl;
cout << "Shape: Unknown" << endl;
}
};
class Circle : public Geometry {
private:
double radius;
double area = 0;
public:
Circle() { radius = 5.0; }
void calArea() {
area = 3.14 * radius * radius;
cout << "Area: " << area << ", Shape: Circle, Radius: " << radius << endl;
}
};
class Square : public Geometry {
private:
double side;
double area = 0.0;
public:
Square() { side = 5.3; }
void calArea() {
area = side * side;
cout << "Area: " << area << ", Shape: Sqaure, Side: " << side << endl;
}
};
class Cube : public Geometry {
private:
double length;
double width;
double height;
double area;
public:
Cube() {
length = 4.0;
width = 4.0;
height = 4.0;
}
void calArea() {
area = 6 * length * width;
cout << "Area: " << area << ", Shape: Cube, Length: " << length
<< ", Width: " << width << ", Height: " << height << endl;
}
};
int main() {
const int SIZE = 10;
int i;
std::vector<std::unique_ptr<Geometry>> shapes;
for (i = 0; i < SIZE; i ) {
int choice = 1 rand() % 3;
if (choice == 1) {
shapes.emplace_back(new Circle());
}
else if (choice == 2) {
shapes.emplace_back(new Square());
}
else if (choice == 3) {
shapes.emplace_back(new Cube());
}
}
for (autoamp; ptr : shapes) {
ptr->calArea();
}
return 0;
}
Комментарии:
1. Ваш код верен. Я думаю, что операция забывает напечатать площадь круга внутри метода calArea() класса Circle.
2. @Job_September_2020 Спасибо! Это вызвано тем, что ОП забыл добавить
area
печать в некоторые функции, я исправил это сейчас!
Ответ №2:
Вы пытались вызвать фигуры[i] для значений i=от 0 до 9. Эти значения еще не были присвоены. Таким образом, вы пытаетесь получить доступ к форме в области памяти, которая не находится в памяти, назначенной вашему приложению, что должно привести к ошибке сегментации. Скорее всего, это связано с отсутствующей скобкой между вашими утверждениями for.
Примечание: Вам было бы легче диагностировать это, если бы вы использовали соглашение о программировании, объявляющее временные переменные в наименьшей области. То есть, если оба ваших заявления » за » гласят
for(int i = 0; i < SIZE; i ) {
вы бы получили значимую ошибку при попытке дважды объявить i и смогли бы исправить опечатку.