1

I'm trying to write a function that will change the size of a dynamic array to a new size. In my header file, I have:

Image **images; //pointer to a dynamic array of image pointers
int maximum; //size

I want to do this by allocating a new array and copying the values over without changing their indices. If there are non-null pointers outside the range newmax, then we cant do this. So heres what I have:

There are no compilation or runtime errors. However, I find that the new array isnt getting sized right. When I run the following test case:

I should get an index out of bounds error, but instead the system lets it slide. Can anyone see the mistake? I've looked for hours but cant find anything.

12
  • 8
    you can use std::vector<Image*> instead of Image** and save some time Commented Feb 13, 2011 at 22:49
  • 2
    What Andy T said, times 100 :) Once you're familiar with vector, you'll never have to worry about this again! Commented Feb 13, 2011 at 22:51
  • 1
    Why would you expect an out of bounds error? Are you throwing one from addpicture() Commented Feb 13, 2011 at 23:01
  • 2
    @iRobot: Nope, it shouldn't. It's undefined behavior. Commented Feb 13, 2011 at 23:05
  • 2
    @iRobot: To clarify, C++ does not do bounds checking on arrays. Commented Feb 13, 2011 at 23:09

2 Answers 2

1
  images=newArray;
  for (int i =0;i<newmax;i++)
        *images[i]=*newArray[i];

This is odd. images and newArray are now the same, hence no need to copy the contents of newArray back to itself. So remove this loop? Also, need to add:

 maximum = newmax;

If the '1' is the index, this should cause

 firstScene->addpicture("red10.bmp", 1, 13, 72);

to give an out of bounds error, whereas at the moment it might seg fault?

Sign up to request clarification or add additional context in comments.

5 Comments

Wow thats it! I needed maximum=newmax. I completely overlooked that part. Question: does images=newArray just assign the memory address of newArray to images? Doesnt newArray go out of scope as soon as the function call is over?
newArray is a pointer to an array. Yes the assignment just copies the pointer. So yes, the original pointer it goes out of scope, but the array it points to is on the heap and remains there. images then continues to point to that array.
So the pointer of newArray goes out of scope, but since we copied it over to images, its still alive?
PS. Nothing wrong with learning how to implement your own dynamic array. Standard library containers are fantastic and should be the default for production code, but if you never try to implement your own, you'll not got the most out of them.
'still alive' in C++ really means that you can still navigate to it. There is no garbage collection etc what would clean it up anyway.
0

You should extract this functionality to a separate class and have a data member in Scene of that type:

struct ImagePtrVector {
  typedef Image *value_type;
  typedef int size_type;

  ImagePtrVector() : _begin (), _end (), _end_alloc () {}
  ~ImagePtrVector() {
    for (value_type x = _begin; x != _end; ++x) {
      delete *x;
    }        
    delete[] _begin;
  }

  // Either define these two yourself or mark private:
  ImagePtrVector(ImagePtrVector const &x);
  ImagePtrVector& operator=(ImagePtrVector const &x);

  value_type& operator[](size_type index) {
    assert(0 <= index);  // Or other checking as you like.
    assert(index < size());
    return _begin[index];
  }
  value_type const& operator[](size_type index) const {
    assert(0 <= index);  // Or other checking as you like.
    assert(index < size());
    return _begin[index];
  }

  size_type size() const { return _end - _begin; }
  size_type capacity() const { return _end_alloc - _begin; }

  void reserve(size_type capacity) {
    if (this->capacity() < capacity) {
      value_type *new_begin = new value_type[capacity];
      // Exception-safe only because I know the below won't throw.

      std::copy(_begin, _end, new_begin);
      _end_alloc = new_begin + capacity;
      _end = new_begin + this->size();
      delete[] _begin;
      _begin = new_begin;
    }
  }

  void resize(size_type size) {
    reserve(size);
    for (size_type diff = size - this->size(); diff > 0; --diff) {
      *_end++ = new Image();
    }
  }

  // Add push_back, begin/end, etc. to taste.

private:
  value_type *_begin, *_end, *_end_alloc;
};

The differences from std::vector and boost::ptr_vector are not coincidence, and you should evaluate whether you really need to write a special container or can reuse an existing generic container.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.