Search code examples
c++segmentation-faultoperator-overloadingdynamic-memory-allocationdynamic-arrays

Segmentation fault: 11 ? C++


Can you tell why does this generate segmentation error? Problem seems to occur when operator[] is called and when I don't call it, goes fine. operator[] is supposed to return a reference to the element with index i.. any help would be great..

//dynamic_array.cpp file

#include <iostream>

#include "dynamic_array.h"

using namespace std;

dynamic_array::dynamic_array() {

        int *array;
        array=new int[4];
        array[0]=3;
        size = 4;
        allocated_size = 5;         
}

dynamic_array::~dynamic_array() {
    delete [] array;
}

int dynamic_array::get_size(void) const {
    return size;
}

int dynamic_array::get_allocated_size(void) const {
    return allocated_size;

}

int& dynamic_array::operator[](unsigned int i) {
        return array[i];
       }
//test.cpp file

#include <iostream>
#include <stdlib.h>

#include "dynamic_array.h"

using namespace std;


int main() {
  dynamic_array a;

  cout << a[0];

}
 //dynamic_array.h file

 using namespace std;

 class dynamic_array {
 public:
      enum {
       BLOCK_SIZE = 5,
       SUBSCRIPT_RANGE_EXCEPTION = 1,
       MEMORY_EXCEPTION = 2,
   };

   dynamic_array();

   ~dynamic_array();

   int get_size(void) const;

   int get_allocated_size() const;

   int& operator[](unsigned int i);

   class exception {
       public:
           exception(int n0) { n = n0; };
           int n;
   };
  private:

   int *array; // pointer to dynamically allocated memory
   int allocated_size; // total number of elements in allocated memory
   int size; // number of active elements
   };

Solution

  • The local declaration

        int *array;
    

    shadows the member array. So the following code uses the local variable, not the member. Hence the member is uninitialized.


    Instead of creating your own dynamic array, use std::vector.

    That's safer and more convenient.


    In other news:

    • The get prefix in e.g. get_size is a Java-ism.
      In C++ a get prefix has no advantage, and it makes the code less readable. For example, standard library containers have a size method, not a get_size.

    • Using void as a formal argument declaration, as in get_size(void), is a C-ism.
      In C it has the important effect of telling the compiler that there really are no arguments, as opposed to any arguments. In C++ () indicates that.

    • Not having also a const version of operator[] is inconsistent with earlier use of const.
      Consistency is very important in programming. Our expectation, e.g. when maintaining code, is that it's consistent. Code that's inconsistent adds costly man-hours to maintenance.

    • The ALL UPPERCASE identifiers for constants are a Java-ism.
      Java lacks a preprocessor, and inherited the all uppercase convention from early C, which lacked const. C++ has both const and a preprocessor. Having const there's generally no need to use #define for constants (as in early C), and having a preprocessor there's a good tecnical reason to not use all uppercase (it conflicts with the convention for macro names). In addition many/most programmers see all uppercase as shouting. It hurts.

    • The class exception should better be derived from std::exception.
      Instead of inventing one's own exception class that can carry an error code, just use std::system_error. That's what it's for. Alternatively, derive a class from std::runtime_error, or use std::runtime_error directly.