【发布时间】:2020-03-12 04:58:43
【问题描述】:
按照其他人的建议,使用完整代码重新发布。刚刚使用导致分段错误的硬编码参数更新了主函数。
将 width 和 height 更改为其他值可以让程序正常运行,例如分别为 500 和 433。
主文件:
#include <cstdint>
#include <iostream>
#include <sstream>
#include <vector>
#include <cmath>
#include "sierpinski.h"
Triangle::Triangle() {
this->pixels = nullptr;
this->top = Coordinate();
this->left = Coordinate();
this->right = Coordinate();
this->fg_color = 0;
this->area = 0.0;
}
Triangle::Triangle(uint32_t* pixels, Coordinate top, Coordinate left, Coordinate right, uint32_t fg_color) {
this->pixels = pixels;
this->top = top;
this->left = left;
this->right = right;
this->fg_color = fg_color;
this->area = calculateArea(top, left, right);
}
void Triangle::DrawLines(Coordinate top, Coordinate left, Coordinate right) {
int width = getWidth(this->left, this->right);
//left to top
std::vector<Coordinate> line = left.Bresenham(top);
for (unsigned int i = 0; i < line.size(); i++) {
this->pixels[width * line[i].getY() + line[i].getX()] = this->fg_color;
}
line.clear();
// left to right
line = left.Bresenham(right);
for (unsigned int i = 0; i < line.size(); i++) {
this->pixels[width * line[i].getY() + line[i].getX()] = this->fg_color;
}
line.clear();
// top to right
line = top.Bresenham(right);
for (unsigned int i = 0; i < line.size(); i++) {
this->pixels[width * line[i].getY() + line[i].getX()] = this->fg_color;
}
}
void Triangle::Sierpinski(Coordinate top, Coordinate left, Coordinate right, const double min_area) {
if (calculateArea(top, left, right) < min_area) {
return;
}
DrawLines(top, left, right);
Triangle triangle(this->pixels, top, left, right, this->fg_color);
Sierpinski(top, top.Midpoint(left), top.Midpoint(right), min_area);
Sierpinski(top.Midpoint(left), left, left.Midpoint(right), min_area);
Sierpinski(top.Midpoint(right), left.Midpoint(right), right, min_area);
}
uint32_t* Triangle::getPixels() {
return this->pixels;
}
uint32_t Triangle::getFg_color() {
return this->fg_color;
}
double Triangle::getArea() {
return this->area;
}
double Triangle::getWidth(Coordinate left, Coordinate right) {
return left.distance(right);
}
double Triangle::calculateArea(Coordinate top, Coordinate left, Coordinate right) {
return std::abs(top.getX() * (left.getY() - right.getY()) + left.getX() * (right.getY() - top.getY()) + right.getX() * (top.getY() - left.getY())) / 2.0;
}
Coordinate::Coordinate() {
this->x = 0;
this->y = 0;
}
Coordinate::Coordinate(int x, int y) {
this->x = x;
this->y = y;
}
Coordinate::Coordinate(const Coordinate &other) {
this->x = other.x;
this->y = other.y;
}
int Coordinate::getX() {
return this->x;
}
int Coordinate::getY() {
return this->y;
}
double Coordinate::distance(Coordinate other) {
return std::sqrt(std::pow((this->x - other.x), 2) + std::pow((this->y - other.y), 2));
}
Coordinate Coordinate::Midpoint(Coordinate other) {
double midX = (this->x + other.getX()) / 2;
double midY = (this->y + other.getY()) / 2;
return Coordinate(midX, midY);
}
int Coordinate::gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a%b);
}
std::vector<Coordinate> Coordinate::Bresenham(Coordinate other) {
int x1 = this->x, y1 = this->y;
int const x2 = other.x, y2 = other.y;
std::vector<Coordinate> points;
int delta_x(x2 - x1);
signed char const ix((delta_x > 0) - (delta_x < 0));
delta_x = std::abs(delta_x) << 1;
int delta_y(y2 - y1);
signed char const iy((delta_y > 0) - (delta_y < 0));
delta_y = std::abs(delta_y) << 1;
Coordinate newPoint1(x1, y1);
points.push_back(newPoint1);
if (delta_x >= delta_y) {
int error(delta_y - (delta_x >> 1));
while (x1 != x2) {
if ((error > 0) || (!error && (ix > 0))) {
error -= delta_x;
y1 += iy;
}
error += delta_y;
x1 += ix;
Coordinate newPoint2(x1, y1);
points.push_back(newPoint2);
}
} else {
int error(delta_x - (delta_y >> 1));
while (y1 != y2) {
if ((error > 0) || (!error && (iy > 0))) {
error -= delta_y;
x1 += ix;
}
error += delta_x;
y1 += iy;
Coordinate newPoint3(x1, y1);
points.push_back(newPoint3);
}
}
return points;
}
int main() {
int width = 55;
int height = 40;
uint32_t bg_color = 4095617261;
uint32_t fg_color = 2988200782;
double min_area = 1.08;
std::vector<uint32_t> pixels(width * height, bg_color);
Coordinate top, left, right;
top = Coordinate(width / 2, 0);
left = Coordinate(0, height);
right = Coordinate(width, height);
Triangle triangle = Triangle(pixels.data(), top, left, right, fg_color);
triangle.Sierpinski(top, left, right, min_area);
std::cout.write(reinterpret_cast<char *>(pixels.data()), width * height * 4);
}
头文件:
#ifndef SIERPINSKI_H
#define SIERPINSKI_H
#include <vector>
class Coordinate {
public:
Coordinate();
Coordinate(int x, int y);
Coordinate(const Coordinate &other);
int getX();
int getY();
double distance(Coordinate);
Coordinate Midpoint(Coordinate other);
int gcd(int a, int b);
std::vector<Coordinate> Bresenham(Coordinate other);
int countPoints(Coordinate other);
std::vector<Coordinate> getPoints(Coordinate other);
private:
int x;
int y;
};
class Triangle {
public:
Triangle();
Triangle(uint32_t* pixels, Coordinate top, Coordinate left, Coordinate right, uint32_t fg_color);
void DrawLines(Coordinate top, Coordinate left, Coordinate right);
void Draw(double min_area);
void Sierpinski(Coordinate top, Coordinate left, Coordinate right, double min_area);
double calculateArea(Coordinate top, Coordinate left, Coordinate right);
uint32_t* getPixels();
uint32_t getFg_color();
double getArea();
Coordinate top, left, right;
double getWidth(Coordinate left, Coordinate right);
private:
uint32_t* pixels;
uint32_t fg_color;
double area;
};
#endif
使用 gdb 后,我的 Bresenham 函数中似乎出现了错误:
points.push_back(newPoint3);
但其他用户表示,seg 错误可能并不完全发生在 gdb 所说的位置。如果有人能提供进一步的见解,将不胜感激。
【问题讨论】:
-
建议:将命令行参数替换为您知道会暴露该错误的值。当有人根据使用不同输入发现的不同错误的解决方案来回答问题时,这真的很烦人。
-
旁注:sierpinski.h 使用
uint32_t,但不包括<cstdint>。由于 main.cpp 中包含 sierpinski.h 的顺序,目前这不是一个错误,但这可能会在稍后重新咬你。 -
感谢旁注,我还在我的原始帖子中包含了一个暴露错误的案例,对吗?我对您的第一条评论感到困惑。
-
我看到了输入,但为什么有输入呢?将它们硬编码到程序中,以免出错。
-
也无关:
Coordinate中不需要复制构造函数。其中注意到默认的复制构造函数无法处理。请参阅Rule of Zero。不应该改变任何事情 WRT 错误。
标签: c++ debugging vector segmentation-fault gdb