1

我对 C++ 还很陌生,我遇到的这个问题让我在过去 2 个小时内都感到困惑。我要做的是创建一个指向我的类 Word 对象的指针数组,因此是一个二维数组,即**wordPtrList. 然后我需要删除数组中某些对象的内存并将它们的指针设置为空。我在下面写了一个我想要完成的小版本。

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;
    }

};

但是,当我这样做时,我得到:

正常块后检测到调试错误堆损坏

这是在 Windows 7 上的 VS 2010 中。

所以我要问的是,如何删除对象的内存以便可以设置wordPtrList[1]为 Null?

4

4 回答 4

2

看看这段代码:

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

问题出在i+1用作索引的最后一行,它超出了范围,因为当循环退出时,值i已经是3;这意味着i+14您分配cArray为:

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

解决方案是这样的:

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

也就是说,使用i代替i+1; 或者干脆使用3.


在 C++ 中,您可以std::fill代替手动循环,如下所示:

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

最好尽量避免使用char*with new,而更喜欢使用 using std::string

于 2012-05-05T05:46:57.157 回答
2

您正在为 cArray 分配 4 个字节(意味着您有权写入字节 0 到 3),然后写入 cArray[4]。您还在 Word 构造函数中分配了一个太小的字节。

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

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

应该做的伎俩。

于 2012-05-05T05:49:55.803 回答
0

正如其他人所说,您基本上是在访问超出数组范围的数组索引。

我会选择 Nathan Wiebe 的解决方案。

将来,当您可以选择执行此操作时,建议使用它,std::vector<T>因为这将允许您将所需的任何类型存储在可动态调整大小的数组中。换句话说,如果您不访问超出向量范围的索引,您可以执行以下操作:

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;

};
于 2012-05-05T06:07:18.663 回答
0

代码中有两个明显的错误(当您退出第一个循环时,变量的值是i多少?调用strlen时您是否记得考虑空终止符所需的空间?)。

另请注意,c 字符串不是“空终止”,它们是“NUL 终止”,大写字母且只有一个“L”。NUL是所有位都设置为零的 ASCII 控制字符的名称,在 C++ 中用 . 表示'\0'。在一个地方,您使用NUL字符作为空指针,虽然这在技术上是正确的(由于 C++ 语言的设计错误),但最好理解这两个概念是完全不同的。

于 2012-05-05T05:56:06.803 回答