1

I am fairly new to C++, and this problem I am having has had me stumped for like the last 2 hours. What I am trying to do is create an array of pointers to my class Word objects, so a 2 dimensional array, which is **wordPtrList. Then I need to delete the memory of certain objects in the array and set their pointers to null. I have written a smaller version of what I am trying to accomplish below.

int main()
{
    char *cArray;
    cArray = new char[4];
    int i;

    for (i = 0; i < 3; i++)
        cArray[i] = 'a';

    cArray[i + 1] = '\0';   //cArray is a null terminated string

    Word **wordPtrList;
    wordPtrList = new Word* [3];

    for (i = 0; i < 3; i++)
    {
        wordPtrList[i] = new Word(cArray);
    }

    wordPtrList[1]->del();
    delete wordPtrList[1];
    wordPtrList[1] = '\0';

    return 0;
}

class Word
{
private:
    char* ptr_;
    int len_;
public:
    Word(const char* word)
    {
        len_ = strlen(word);
        ptr_ = new char[len_];      
        strcpy(ptr_, word);
    }
    ~Word()
    {
        delete [] ptr_;
        ptr_ = 0;
    }


    void del()
    {
        delete [] ptr_;
        ptr_ = 0;
        return;
    }

};

When I do this however, I get:

Debug Error Heap Corruption Detected after normal block

This is in VS 2010 on Windows 7.

So what I am asking is, how do I delete the memory of my object so that I can set wordPtrList[1] to Null?

3
  • 1
    Hi. First thing I noticed: cArray[i + 1] = '\0'; i+1 equals 4, which is beyond the limit Commented May 5, 2012 at 5:44
  • @A.J. is right. Your second problem is that strlen returns the length of the string excluding the null byte. That means you have to add +1 to your new call Commented May 5, 2012 at 5:46
  • 1
    Ok yea, I see both of these now. Thanks for the help everyone Commented May 5, 2012 at 5:57

4 Answers 4

2

You are allocating 4 bytes to cArray (meaning you have access to write to bytes 0 through 3), and then writing to cArray[4]. You also allocate one byte too small in the Word constructor.

char *cArray;
cArray = new char[4];
int i;

for (i = 0; i < 3; i++)
    cArray[i] = 'a';
cArray[i] = '\0';   //cArray is a null terminated string - i is now 3

and

 Word(const char* word)
 {
    len_ = strlen(word);
    ptr_ = new char[len_ + 1];      
    strcpy(ptr_, word);
 }

should do the trick.

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

Comments

2

Look at this code:

for (i = 0; i < 3; i++)
    cArray[i] = 'a';
cArray[i + 1] = '\0';   //cArray is a null terminated string

The problem is at the last line which is using i+1 as index, which is going out of range, as by the time the loop exits, the value of i is already 3; that means i+1 will become 4 which cannot be a valid index when you've allocated cArray as:

cArray = new char[4]; //taken from your code

The solution is this:

cArray[i] = '\0';   //Now, it is correct. Here i is equal to 3

That is, use i instead of i+1; Or simply use 3.


In C++, you could std::fill instead of manual loop, as:

std::fill(cArray, cArray + 4, 'a'); //done

Even better avoid using char* with new as much as possible, and prefer using std::string instead.

Comments

0

There are two obvious off-by-one errors in the code (when you get out of the first loop what is the value of the variable i? when calling strlen did you remember to consider the space needed by the null terminator?).

Also please note that c strings are not "null terminated", they are "NUL terminated" with uppercase letters and only one "L". NUL is the name of the ASCII control character with all bits set to zero and is represented in C++ with '\0'. In one place you used NUL character as a null pointer, and while this is technically correct (because of a design bug of the C++ language) it's better to understand that the two concepts are quite different.

5 Comments

I am slightly confused by this. What exactly are the differences between NUL and '\0'?
There is no conceptual difference between NUL and '\0', the first is the official ASCII name and the second is how you write it in a C++ program. The difference is between NULL (the "null pointer") and '\0'. In your code after deleting the class you are assigning '\0' to the pointer and this is conceptually wrong. Unfortunately because of a design bug in the C++ language itself the NUL character can be used as null pointer so the compiler will not complain and the code is formally correct. It's important you understand the difference however.
Oh ok, I am not sure why I set it equal to '\0' there. So then when you are done using a pointer, would you want to set it equal NULL like ptr = NULL; Also is this the same as ptr = 0? Sorry for all of the questions.
@pistolpete333: Yes. Using ptr=NULL; is the same as using ptr=0;. The first makes more evident that the variable being set is a pointer so should be preferred (but I've to admit that I'm used to type 0 instead). Even if it's more typing remember that code is often written once and read many times over the lifespan of a program, so investing some writing time to ease reading phase is a good thing. Using '\0' is instead a no-no ... like I said it works but just because of a "bug" of the C++ language. Technically you can use also ptr=3-2-1; but you wouldn't do that, right? ;-)
Awesome, thanks a ton for clearing that up for me. I will definitely be aware of this in the future.
0

As others have said, you're basically accessing an array index which is out of bounds of the array.

I would go with Nathan Wiebe's solution.

In the future, when you have the option to do this, it's recommended to use std::vector<T> as that will allow you to store any type you wish in a dynamically resizeble array. In other words, providing you don't access an index which is outside of the vector's bounds, you could do something like this:

std::vector< char* > str;

for( size_t i = 0; i < str.size(); ++i )
{
   str.push_back( 'a pointer to a block of memory consisting of characters' ); 
}

class Word
{
public:
    Word( const char* str )
    {
        mStrs.push_back( str );
    }
    ~Word( void )
     {
         for( size_t i = 0; i < mStrs.size(); ++i )
         {
             if( mStrs[ i ] )
             {
                 delete mStrs[ i ];
                 mStrs[ i ] = NULL;
             }
         }

         mStrs.clear();
     }

private:
    void del( size_t index )
    {   
         if( index > mStrs.size() )
         {
              //error - throw new exception or something
         }

         delete mStrs[ index ];
    }

    std::vector< const char* > mStrs;

};

2 Comments

Believe me, I would love to use vectors, but it was required we use character arrays for this hw assignment. Are there any advantages to using character arrays vs vectors?
It depends. IF you're allocating a single string and you need that, it's better to use std::string, but if you need to use a char*, then a char* makes more sense as opposed to a vector provided you know what you're doing. A great reference on C++ would the following faq, as well as this article in particular: parashift.com/c++-faq-lite/containers.html

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.