使用其他人建议的完整代码重新发布。刚刚使用导致分段错误的硬编码参数更新了主函数。
将宽度和高度更改为其他值可使程序正常运行,例如分别为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所说的确切发生。如果有人可以提供进一步的见解,将不胜感激。
答案 0 :(得分:3)
崩溃发生在这里:
#0 0x00007ffff7b12c46 in malloc () from /lib64/libc.so.6
#1 0x00007ffff7e5e059 in operator new(unsigned long) () from /lib64/libstdc++.so.6
#2 0x00000000004035ac in __gnu_cxx::new_allocator<Coordinate>::allocate (this=0x7fffffffd3f0, __n=2) at /usr/include/c++/9/ext/new_allocator.h:114
#3 0x000000000040335b in std::allocator_traits<std::allocator<Coordinate> >::allocate (__a=..., __n=2) at /usr/include/c++/9/bits/alloc_traits.h:444
#4 0x0000000000402fe2 in std::_Vector_base<Coordinate, std::allocator<Coordinate> >::_M_allocate (this=0x7fffffffd3f0, __n=2) at /usr/include/c++/9/bits/stl_vector.h:343
#5 0x00000000004028be in std::vector<Coordinate, std::allocator<Coordinate> >::_M_realloc_insert<Coordinate const&> (this=0x7fffffffd3f0, __position={x = 0, y = 0}, __args#0=...) at /usr/include/c++/9/bits/vector.tcc:440
#6 0x00000000004024a0 in std::vector<Coordinate, std::allocator<Coordinate> >::push_back (this=0x7fffffffd3f0, __x=...) at /usr/include/c++/9/bits/stl_vector.h:1195
#7 0x0000000000401f48 in Coordinate::Bresenham (this=0x7fffffffd4c8, other=...) at t.cc:205
#8 0x0000000000401610 in Triangle::DrawLines (this=0x7fffffffd580, top=..., left=..., right=...) at t.cc:86
#9 0x0000000000401823 in Triangle::Sierpinski (this=0x7fffffffd580, top=..., left=..., right=..., min_area=1.0800000000000001) at t.cc:96
#10 0x0000000000402154 in main () at t.cc:225
任何,当您在malloc
中崩溃时,您应该立即怀疑堆损坏。
address sanitizer(在您的编译和链接命令行中添加-fsanitize=address
)是这样的:
=================================================================
==5470==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x625000002360 at pc 0x000000401e84 bp 0x7fffffffcdb0 sp 0x7fffffffcda0
WRITE of size 4 at 0x625000002360 thread T0
#0 0x401e83 in Triangle::DrawLines(Coordinate, Coordinate, Coordinate) /tmp/t.cc:76
#1 0x4028c5 in Triangle::Sierpinski(Coordinate, Coordinate, Coordinate, double) /tmp/t.cc:96
#2 0x4043df in main /tmp/t.cc:225
#3 0x7ffff707ef32 in __libc_start_main (/lib64/libc.so.6+0x23f32)
#4 0x40126d in _start (/tmp/a.out+0x40126d)
0x625000002360 is located 0 bytes to the right of 8800-byte region [0x625000000100,0x625000002360)
allocated by thread T0 here:
#0 0x7ffff768a9d7 in operator new(unsigned long) (/lib64/libasan.so.5+0x10f9d7)
#1 0x406f82 in __gnu_cxx::new_allocator<unsigned int>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x406e67 in std::allocator_traits<std::allocator<unsigned int> >::allocate(std::allocator<unsigned int>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x406b8f in std::_Vector_base<unsigned int, std::allocator<unsigned int> >::_M_allocate(unsigned long) /usr/include/c++/9/bits/stl_vector.h:343
#4 0x40663e in std::_Vector_base<unsigned int, std::allocator<unsigned int> >::_M_create_storage(unsigned long) /usr/include/c++/9/bits/stl_vector.h:358
#5 0x405a5c in std::_Vector_base<unsigned int, std::allocator<unsigned int> >::_Vector_base(unsigned long, std::allocator<unsigned int> const&) /usr/include/c++/9/bits/stl_vector.h:302
#6 0x404bf0 in std::vector<unsigned int, std::allocator<unsigned int> >::vector(unsigned long, unsigned int const&, std::allocator<unsigned int> const&) /usr/include/c++/9/bits/stl_vector.h:521
#7 0x403faa in main /tmp/t.cc:218
#8 0x7ffff707ef32 in __libc_start_main (/lib64/libc.so.6+0x23f32)
SUMMARY: AddressSanitizer: heap-buffer-overflow /tmp/t.cc:76 in Triangle::DrawLines(Coordinate, Coordinate, Coordinate)
所以您确实有堆损坏(分配的堆缓冲区溢出)。
希望这是足够的信息,您可以在程序中找到逻辑错误。
P.S。
看起来您正在分配height
* width
像素的矩形,然后尝试从height * width
s像素画一条线。您可能有一个错误的错误-有效像素索引的范围为[0 .. width-1] * [0 .. height-1]
。
当我在向量中保留(width+1) * (height+1)
空间时,问题就消失了。