malloc(): memory corruption (fast) c++

30,706

Solution 1

Since you didn't post a complete program, here are some things you should look out for:

convexHull(Point Points[], int n)

Nowhere in that function do you check if n is within bounds of the Points array. You should be using vector throughout your function. For example:

 int ymin = Points[0].getY();
 int min = 0;
 for (int i = 1; i < n; i++) {
    int y = Points[i].getY();

If I pass a NULL pointer as the first argument (or even an invalid pointer), or if n is too large, you have an access violation. Using vectors greatly reduces or outright removes these issues. With vector, you have the size() member function to do sanity tests to ensure that Point has the relevant number of entries. Right now, there is no way to do such tests in your function.

Next issue:

S.push(Points[0]);
S.push(Points[1]);
S.push(Points[2]);

How do you know there are at least 3 entries in point? You don't know, and there is no way in that function to check. All you have is a pointer being passed, and some arbitrary number n. If you're using C++, you should not be in the habit of deliberately coding in a 'C'-like style. You have vector, so use it to its advantage.

Next issue:

qsort(&Points[1], n - 1, sizeof (Point), compare);

Since you didn't post what Point is, this usage of qsort() leads to undefined behavior if Points is a non-POD type.

Stop using qsort(). Usage of qsort() within a C++ program is an indication that the coder is either 1) a C programmer who is using what they're used to (with the surprising unexpected reuslts that usually follow) or 2) A newbie C++ programmer who is reading C books or programs as a guidance in writing proper C++ programs.

Use std::sort() -- you're writing a C++ app, not a C application. The std::sort is typesafe, easier to use and setup, and works for POD and non-POD types that follow a strict-weak-ordering.

Solution 2

By the look of the error, and the place you are saying it crashes (a declaration), it very well may be in the qsort function. It is the only C library call you have in the code, and the error can't be in the declaration of the stack since it is just a declaration.

The first thing you should do is check bounds

vector<Point> convexHull(Point Points[], int n) {
  vector<Point> v;
  if(n <= 3){ 
     // error
  }else{
    //the chunk of code
  } 
  return v;
}

But wait... there's more, suppose you want to replace the Points array with a vector

std::vector<Point> convexHull(vector<Point>::iterator begin, vector<Point>::iterator end) {
  std::vector<Point> returnVal;
  if(n <= 3){ 

  }else{
    //the chunk of code
  } 
  return returnVal;
}
// just don't forget to check your returnVal for empty size, error handling is a must

Or you could just use your c style old school method with a vector... which i don't recommend because you stop learning about iterators, which you should.

vector<Point> Points(100);
vector<Point> v;
if(convexHull(&Points[0], Points.size())) ///< how would you be testing this
{
   //yay
}

Oh, and by the way, implementing std::sort is really easy, don't be afraid, it is like this

std::sort (&Points[1], &Points[1]+ (n-1));

Which would be easier if Points where iterators

std::sort (begin+1, end);

You could even go further and use std::advance, which you should

vector<Point>::iterator it = begin;   
std::advance(it,1);
std::sort (it, end);

So in conclusion how would the first part look with iterators?

std::vector<Point> convexHull(vector<Point>::iterator begin, vector<Point>::iterator end)
{
  vector<Point> v;
  // Find the bottommost Point
  int ymin = begin->getY();
  vector<Point>::iterator l_it = begin; 
  vector<Point>::iterator min_position = begin;
  std::advance(l_it, 1);
  for (; l_it != end; ++l_it) 
  {
      int y = l_it->getY();

      // Pick the bottom-most or chose the left most Point in case of tie
      if ((y < ymin) || (ymin == y && l_it->getX() < min_position->getX()))
      {
          ymin = l_it->getY();
          min_position = l_it;
      }
   /// MORE CODE
}
Share:
30,706
ديناصور الأمة
Author by

ديناصور الأمة

Software engineer, mainly in web development. I have created some web sites and applications using PHP with differents Yii and Symfony2 frameworks and Wordpress CMS. I have also created a JEE application using Hibernate, JSF and Spring frameworks.

Updated on July 06, 2022

Comments

  • ديناصور الأمة
    ديناصور الأمة almost 2 years

    I'm new with c++ and I'm trying to calculate the convex hull of a Point(x,y,z) set using C++.

    I have called the following method in the main method:

    vector<Point> convexHull(Point Points[], int n) {
        vector<Point> v;
        // Find the bottommost Point
        int ymin = Points[0].getY();
        int min = 0;
        for (int i = 1; i < n; i++) {
            int y = Points[i].getY();
    
            // Pick the bottom-most or chose the left most Point in case of tie
            if ((y < ymin) || (ymin == y && Points[i].getX() < Points[min].getX()))
                ymin = Points[i].getY(), min = i;
        }
        // Place the bottom-most Point at first position
        Points[min] = Points[0].swap(Points[min]);
    
        // Sort n-1 Points with respect to the first Point. A Point p1 comes
        // before p2 in sorted ouput if p2 has larger polar angle (in 
        // counterclockwise direction) than p1
        p0 = Points[0];
        qsort(&Points[1], n - 1, sizeof (Point), compare);
    
        // Create an empty stack and push first three Points to it.
        stack<Point> S; //  on debug the project I find that the problem is here 
        S.push(Points[0]);
        S.push(Points[1]);
        S.push(Points[2]);
    
        // Process remaining n-3 Points
        for (int i = 3; i < n; i++) {
            // Keep removing top while the angle formed by Points next-to-top, 
            // top, and Points[i] makes a non-left turn
            while (orientation(nextToTop(S), S.top(), Points[i]) != 2)
                S.pop();
    
            S.push(Points[i]);
        }
    
        // Now stack has the output Points, print contents of stack
        while (!S.empty()) {
            Point p = S.top();
            cout << "(" << p.getX() << ", " << p.getY() << ", " << p.getZ() << ")" << endl;
            v.push_back(Point(p.getX(), p.getY(), 0));
            S.pop();
        }
        return v;
    }
    

    It give this error:

    *** glibc detected *** /home/user/NetBeansProjects/DGILOG-ask/dist/Debug/GNU-Linux-x86/dgilog-task: malloc(): memory corruption (fast): 0x08de1238 ***
    

    I have searched in the web for the same error but I don't have understand what should I do.

    Point.cpp

    #include <iostream>
    #include <math.h>
    #include <ostream>
    
    using namespace std;
    
    #include "Point.h"
    
    Point::Point() : x(0), y(0), z(0) {
    }
    
    Point::Point(ostream &strm) {
        strm << "Type the abscissa: ", cin >> this->x;
        strm << "Type the ordinate: ", cin >> this->y;
        strm << "Type the applicate: ", cin >> this->z;
    }
    
    Point::Point(float x, float y, float z) : x(x), y(y), z(z) {
    }
    
    /**
     * Destructor
     */
    Point::~Point() {
    }
    
    //Other methods
    
    float Point::dist2D(Point &other) {
        float xd = x - other.x;
        float yd = y - other.y;
        return sqrt(xd * xd + yd * yd);
    }
    
    float Point::dist3D(Point &other) {
        float xd = x - other.x;
        float yd = y - other.y;
        float zd = z - other.z;
        return sqrt(xd * xd + yd * yd + zd * zd);
    }
    
    Point Point::swap(Point p) {
        Point aux(x, y, z);
        x = p.x;
        y = p.y;
        z = p.z;
        return aux;
    }
    
    void Point::print(ostream &strm) {
        strm << "Point(" << this->x << "," << this->y << "," << this->z << ")" << endl;
    }
    
    bool Point::operator<(const Point &p) const {
        return x < p.x || (x == p.x && y < p.y);
    }
    

    Thanks.

    • clcto
      clcto over 10 years
      Are you sure your Points[] has at least 3 elements? Have you stepped through this with a debugger?
    • Tom Fenech
      Tom Fenech over 10 years
      What you should do is compile your code with -g and then run it through valgrind
    • PaulMcKenzie
      PaulMcKenzie over 10 years
      1) Quit using qsort. Learn to use std::sort. 2) Why are you using vector<Point> (good), and at the same time using arrays of Point (questionable)?
    • pm100
      pm100 over 10 years
      run the program under valgrind (if you can)
    • Eric Fortin
      Eric Fortin over 10 years
      Can you post definition of Point ? Especially the implementation of swap.
    • Jan Hudec
      Jan Hudec over 10 years
      Also learn to iterate with iterators, not indices. It works for all collections and many other objects (including plain old arrays; pointer is iterator) while indices work only for vectors and plain old arrays.
    • ديناصور الأمة
      ديناصور الأمة over 10 years
      @clcto Yes has more than 3 elements. I have tried to display his content with for-loop. It works well.
    • ديناصور الأمة
      ديناصور الأمة over 10 years
      @EricFortin I have added the swap method definition
    • ديناصور الأمة
      ديناصور الأمة over 10 years
      @brokenfoot the main is very long but I can post a peace
  • Jan Hudec
    Jan Hudec over 10 years
    I would upvote if it was not for the output argument (yuck; always prefer return value over output parameters; with C++11 move semantics returning vectors is trivial operation), the incorrectly used int return (if you want to check it with if, it should be a bool; and the values are both true too) and the failure to use exceptions.
  • Jan Hudec
    Jan Hudec over 10 years
    Plus std::sort is faster. Often about twice. Because the compiler can inline it.
  • Jan Hudec
    Jan Hudec over 10 years
    It would be nice if you also included the switch to iterators. C++ has many things that have iterators, but no indices and no way to convert them to pointers, so it's a good habit to get into.
  • Claudiordgz
    Claudiordgz over 10 years
    failure to use exceptions? You mean I should use exceptions? We use assertions to achieve that functionality. I don't believe it is wrong or right, it is just the way things are done. Choosing between one or the other should be done from the beginning and stick to it.
  • Jan Hudec
    Jan Hudec over 10 years
    Well, if the function returns the calculated value, than the only, and most convenient too, way to return an error is an exception. Of course calling convexHull... convexHull is well defined for less than 3 points anyway, so it should not return error (except the std::bad_alloc that std::vector::push_back may throw) anyway.
  • Claudiordgz
    Claudiordgz over 10 years
    Seems reasonable, even though it should not fail it maybe the user may want that layer of security.
  • Jan Hudec
    Jan Hudec over 10 years
    Layer of security often comes to bite you somewhere down the road. In most situations the preferred approach is to fail fast and loud, which in most cases means assert or throw. But I agree that what is appropriate error handling depends on a lot of context we don't have here.