如何使用户无法删除动态数组呢?

时间:2011-10-10 16:52:32

标签: c++ pointers dynamic-allocation

在编写响应时,我编写了一些代码,这些代码挑战了我对const指针如何工作的假设。我假设删除函数无法删除常量指针,但正如您将从下面的代码中看到的那样,情况并非如此:

#include <new>
#include <string.h>

class TestA
{
    private:
        char *Array;
    public:
        TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
        ~TestA(){if(Array != NULL){ delete [] Array;} }

        char * const GetArray(){ return Array; }
};

int main()
{
    TestA Temp;
    printf("%s\n",Temp.GetArray());
    Temp.GetArray()[0] = ' '; //You can still modify the chars in the array, user has access
    Temp.GetArray()[1] = ' '; 
    printf("%s\n",Temp.GetArray());
    //Temp.GetArray() = NULL //This doesn't work

    delete [] Temp.GetArray(); //This works?! How do I prevent this?
}

我的问题是,如何将用户访问权限传递给指针(因此他们可以像使用char数组一样使用它),同时使删除功能无法删除它,最好是抛出某种抱怨或异常?

5 个答案:

答案 0 :(得分:6)

如果您的用户使用的是delete[]指针,但他们没有从new[]获得指针,请使用线索将其击中头部。

指针可以解除引用的原因有很多,但不能传递给删除:

  • 其他人会将其删除。
  • 这不是阻止的开始。
  • 它来自malloc或其他非new分配器。
  • 它具有静态而非动态的生命周期。
  • 如果有自动生命。

其中一些将在运行时在异常中显示。其他人稍后会导致崩溃。根据标准,所有都是“未定义的行为”。

假设指针不能用作delete的参数,除非另有明确说明。

如果入门级程序员犯了这个错误,请教育他们。如果“经验丰富”的开发人员正在这样做,请将他们放在简历上解雇。


如果你只是想让它受到伤害,请分配一个大于必要的数组return Array + 1;。如果他们试图使用delete[],现在一切都会爆炸。

实际应用是,(更多)可能会使程序在伪造的删除调用中崩溃,而违规函数仍然在调用堆栈上。原来可能会继续运行一段时间,最后崩溃无辜的代码。所以这有助于你抓住愚蠢的用户。

答案 1 :(得分:5)

delete [] Temp.GetArray(); //This works?! How do I prevent this?

只要它返回char*或其他指针类型,就无法阻止它;如果delete语句中的表达式为const,则无关紧要,因为以下所有内容在C ++中完全有效:

char *pc = f(); 
delete [] pc;  //ok

const char *pc = g(); 
delete [] pc; //ok

char * const pc = h(); 
delete [] pc; //ok

const char * const pc = k(); 
delete [] pc; //ok

但是,如果你改变了这个:

char *Array;

到这个

std::vector<char> Array;

然后你可以通过返回它来实现你想要的目标:

std::vector<char> & GetArray() { return Array; }

底线是:

在C ++中,动态数组的默认选择应该是std::vector<T>,除非你有的理由才能使用它。

答案 2 :(得分:1)

你的const没有效果,你返回一个const指针,而不是指向const char的指针,这就是你想要的。另请参阅Nawaz关于使用向量的建议。

答案 3 :(得分:1)

你真正做的最多的事情就是返回delete不可接受的操作数。这可以是一个RAII对象(比如std :: vector或std :: array),也可以是一个引用(根据你的情况,可能是合适的)。

[Un]幸运的是,C ++让程序员可以做各种偷偷摸摸的事情。

答案 4 :(得分:0)

你不能完全阻止愚蠢,但你可以通过使用访问机制而不是返回实际的数组指针来扼杀它。

char& operator[](size_t index) { return Array[index]; }

这并不能解决像char数组那样对待它的能力,但正如已经指出的那样,如果你发现那个指针,(坏)程序员可以随意对它进行删除。