C ++ segfault,可重现的示例 [英] C++ segfault, reproducible example

查看:64
本文介绍了C ++ segfault,可重现的示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照其他人的建议重新发布完整代码。刚刚使用导致分段错误的硬编码参数更新了主函数。

Reposting with full code, as suggested from others. Just updated the main function with hard coded arguments that causes segmentation fault.

宽度高度更改为其他值可使程序正常运行,例如分别为500和433。

Changing the width and height to something else lets the program run fine, for example 500 and 433 respectively.

主文件:

#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函数如下:

After using gdb, it seemed the error was occuring in my Bresenham function at the line:

points.push_back(newPoint3);

但是其他用户指出,seg错误可能并不是gdb所说的确切位置。如果有人可以提供进一步的见解,将不胜感激。

But other users stated that seg fault may not be occurring exactly where gdb says it is. If anyone can provide further insight it would be greatly appreciated.

推荐答案

崩溃发生在这里:

#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

Any 当您在 malloc 中崩溃时,您应该立即怀疑堆损坏。

Any time you have a crash in malloc, you should immediately suspect heap corruption.

这是地址消毒剂(只需添加 -fsanitize = address 到您的编译和链接命令行):

Here is what address sanitizer (just add -fsanitize=address to your compile and link command lines) says:

=================================================================
==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)

所以确实有堆损坏(分配的堆缓冲区溢出)。

So indeed you have heap corruption (overflow of allocated heap buffer).

希望这对您来说足以在程序中找到逻辑错误。

Hopefully this is enough info for you to find a logic bug in your program.

PS

您似乎正在分配高度 * width 像素,然后尝试从 height * width s像素画一条线。您可能有一个错误的错误-有效像素 indices 的范围是 [0 .. width-1] * [0 .. height-1]

It looks like you are allocating a rectangle of height * width pixels, then try to draw a line from the height * widths pixel. You likely have an off-by-one bug -- valid pixel indices are in the range [0 .. width-1] * [0 .. height-1].

当我保留(width + 1)*(height + 1)空间时在向量中,问题就消失了。

When I reserve (width+1) * (height+1) space in the vector, the problem goes away.

这篇关于C ++ segfault,可重现的示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆