C ++删除使用new分配的char指针

4
在这段代码中,我从文件中获取数字,其中第一个数字是2D数组的大小。
在我的代码中,我正在定义。
char *filename=new char;

我必须使用char *filename,这是练习的要求。一切都运行良好,直到我尝试删除。无论是delete还是delete[]都会导致错误并使程序崩溃。

这是我的完整代码:

#include <iostream>
#include <fstream>
using namespace std;
double **readmat(char *filename, int *size)/////question 2
{
    ifstream read(filename);
    cout << filename << endl;
    if (!read)
    {
        cout << "Can't open file!" << endl;
        exit(1);
    }
    read >> *size;
    double **mat = new double*[*size];
    for (int i = 0; i < *size; i++)
    {
        mat[i] = new double[*size];
        for (int j = 0; j < *size; j++)
        {
            read >> mat[i][j];
        }
    }    
    read.close();    
    return mat;
}
int main()
{
    int size;
    char *filename = new char;
    filename = "text.txt"; 

    double **arr = readmat(filename, &size);
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            cout << arr[i][j]<<"  ,  ";
        }
        cout << endl;
    }
    cout << endl;

    delete filename; //<-------- this crashed my code
    for (int i = 0; i < size; i++)
    {
        delete[] arr[i];
    }
    delete[] arr;
    return 0;
}

这是我的文件外观:

enter image description here

这是运行代码后控制台应用程序的外观:

enter image description here

我期望得到的是这个,但我却收到了以下错误信息:

enter image description here

有人知道这是什么原因导致的吗?我该怎么解决它?


你立即通过将字符串字面量的地址赋值给filename =“text.txt”来覆盖char *filename = new char;所持有的地址。问自己,“现在filename指向哪里?” - David C. Rankin
您正在为 filename 分配一个字符。您可能需要考虑分配更多,例如 64 或 128。 - Thomas Matthews
5个回答

5
你正在尝试删除一个未指向使用new分配的内存的char*。

这一行:

char *filename = new char;

您需要使用new来分配内存(一个单独的char,而不是一串char)。但是,在这行代码中:
filename = "text.txt"; 

你将char*指针改为指向完全不同的内存,因此泄漏了你所使用的new的内存。

然后在这一行中:

delete filename;

你试图删除字面量"text.txt",而不是你使用new创建的char。这就是为什么程序崩溃的原因。
对于你想要做的事情,你需要这样做:
char *filename = new char[strlen("text.txt")+1];
strcpy(filename, "text.txt");
...
delete[] filename;

然而,你真的不应该使用 new/new[] 来为 filename 分配内存。应该使用 std::string 替代:

#include <fstream>
#include <string>

double **readmat(const std::string &filename, int *size)
{
    std::ifstream read(filename.c_str());
    ...
}

int main()
{
    int size;
    double **arr = readmat("text.txt", &size);
    ...
}

或者:

#include <fstream>
#include <string>

double **readmat(const char *filename, int *size)
{
    ifstream read(filename);
    ...
}

int main()
{
    int size;
    std::string filename = "text.txt";

    double **arr = readmat(filename.c_str(), &size);
    // or simply:
    // double **arr = readmat("text.txt", &size);
    ...
}

此外,在进行操作时,您不应该再使用 new[] 来创建矩阵。相反,应该使用 std::vector:

#include <vector>

std::vector< std::vector<double> > readmat(char *filename)
{
    ...

    int size;
    read >> size;

    std::vector< std::vector<double> > mat(size);
    for (int i = 0; i < size; i++)
    {
        mat[i].resize(size);
        for (int j = 0; j < size; j++)
        {
            read >> mat[i][j];
        }
    }    

    return mat;
}

int main()
{
    ...

    std::vector< std::vector<double> > arr = readmat("text.txt");
    size_t size = arr.size();

    for (size_t i = 0; i < size; i++)
    {
        for (size_t j = 0; j < size; j++)
        {
            std::cout << arr[i][j] << "  ,  ";
        }
        std::cout << endl;
    }
    std::cout << endl;

    return 0;
}

4
char *filename = new char;
filename = "text.txt";

这样会创建一个新的字符,然后泄漏掉它,因为指针filename被重新分配给了静态声明的内容。

因此,之后您删除的不是原始字符。

这里存在多个问题(使用new而不是new[]等)。建议忘记一切,使用std::string和STL。


3
这是你问题的源头:
char *filename = new char;
filename = "text.txt";

filename 不再指向动态分配的内存,因此您无法 delete 它(并且您还泄漏了 1 字节的内存)。将声明更改为 const char *filename = "test.txt"; 并删除 delete filename;


2

new char函数在堆上分配一个单个字符。大多数以const char*作为参数的函数都期望指向以空字符(\0)作为定界符的数组的第一个元素的指针(即C风格的字符串)。

在标准C++中,你甚至不应该把字符串字面值赋给char *类型的变量。对于字符串字面值,你不需要动态分配内存,只需使用

const char *filename = "text.txt"; 

同时,您也不应该删除指向字符串字面量的指针。(这很可能是导致错误的原因,您删除了指向字符串字面量的指针)


在标准C++中,您甚至都不应该能够将字符串文字分配给类型为char*的变量。但在C++11之前的版本中是可以的。但是,您是正确的,这并不是一个好习惯。字符串字面值应该被分配给const char*,而C++11及更高版本会强制执行这一点。 - Remy Lebeau
@RemyLebeau 有趣,我不知道 :) - Lukas-T

1

仅需替换

char* filename = new char;

使用

const char* filename = "text.txt";

和删除

delete filename;

这是你最终代码的样子。
int main()
{
    int size;
    const char *filename = "text.txt"; 

    double **arr = readmat(filename, &size);
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            cout << arr[i][j]<<"  ,  ";
        }
        cout << endl;
    }
    cout << endl;

    for (int i = 0; i < size; i++)
    {
        delete[] arr[i];
    }
    delete[] arr;
    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接