C++ Delete关键字导致`未知信号`

6yoyoihd  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(151)

我刚开始学习c++,为了更好地理解内存的工作原理,我尝试在c++中构建一个动态大小的数组。我成功地实现了push和get功能,但当我尝试添加pop功能时,我偶然发现了一个非常奇怪的错误,我在互联网上没有找到任何类似的记录,这是在使用delete关键字释放内存时发生的。
下面是我的代码:

#include <iostream>
#include <cstdlib>

using namespace std;

template <class T>
class Array {
    T* ptr;
    public:
        int size;

        Array(unsigned int original_size) : size(original_size) {
            ptr = (T*) malloc(size * sizeof(T));
        }
        Array () {
            size = 0;
            ptr = 0;
        }

        void set(int pos, T val) {
            ptr[pos] = val;
        }

        T get(int pos) {
            return ptr[pos];
        }

        T operator[] (int i) {
            return get(i);
        }

        void operator() (int pos, T val) {
            set(pos, val);
        }

        void add(T value) {
            ptr = (T*) realloc(ptr, (++size) * sizeof(T));
            set(size - 1, value);
        }

        T pop() {
            T temp = get(--size);

            delete (ptr + size);

            return temp;
        }
};

int main() {

    Array<int> arr(3);
    arr(0, 1);
    arr(1, 2);
    arr(2, 3);

    arr.add(4);
    arr.add(5);
    cout << arr.pop();
    cout << arr.pop();
}

字符串
这段代码在pop方法中调用delete命令后失败,消息是Unknown Signal。你知道我做错了什么吗?

gcmastyq

gcmastyq1#

这里有两个问题。
1.将deletemalloc/realloc一起使用
1.调整delete/free中使用的指针
当您向Array添加元素时,您可以使用malloc()为初始Arrayrealloc()分配内存,并且没有问题。
并将Array分配的内存地址存储在ptr中。
但是在pop()方法中,你可以像这样释放这个分配:

delete (ptr + size);

字符串
虽然delete应该只与new运算符一起使用,因为它会导致未定义的行为,但在这种特殊情况下,编译器会调用free()
所以你基本上告诉malloc()释放内存,但给予了一个错误的地址:指针地址+偏移量。这个偏移量size“损坏”了ptr并混淆了malloc()。你不能简单地释放/删除分配的数组的一部分。我的意思是你可以,但使用realloc()
malloc不知道如何处理,所以它以SIGABRT信号结束:

malloc_printerr (str=str@entry=0x7ffff7d32210 "munmap_chunk(): invalid pointer") at ./malloc/malloc.c:5664


基本上,你也应该在方法pop()中使用realloc(),从Array中删除元素,如下所示:

T pop() {
        T temp = get(--size);
        ptr = (T*) realloc(ptr, (size) * sizeof(T));
        return temp;
    }


或者你可以尝试使用new操作符的重新制作的例子:

template<typename T> 
class Array {
    T* ptr;
    public:
        int size;

        Array () {
            cout << "Array() Constructor" << endl;
            size = 0;
            ptr = 0;
        }

        Array(unsigned int original_size) : size(original_size) {
            cout << "Array(size) Constructor" << endl;
            ptr = new T[size];
        }

        Array(T arr[], int original_size) : size(original_size) {
            cout << "Array(arr[], size) Constructor" << endl;
            ptr = new T[size]; 
            for (int i = 0; i < size; i++)
                ptr[i] = arr[i];
        }
        
        ~Array () {
            cout << "Array() Destructor" << endl;
            delete[] ptr;
        }

        T operator[] (int i) {
            return get(i);
        }

        void operator() (int pos, T val) {
            set(pos, val);
        }

        void set(int pos, T val) {
            ptr[pos] = val;
        }

        T get(int pos) {
            return ptr[pos];
        }

    void push(T value) {
        T* newptr = new T[++size];

        for (int i = 0; i < size - 1; i++)
            newptr[i] = ptr[i];

        newptr[size - 1] = value;
        delete[] ptr;
        ptr = newptr;
    }

    T pop() {
        T temp = get(--size);

        T* newptr = new T[size];

        for (int i = 0; i < size; i++)
            newptr[i] = ptr[i];

        delete[] ptr;
        ptr = newptr;
        return temp;
    }
};


希望它能帮助你从这个答案和下面的评论中学到一些东西。

相关问题