【问题标题】:c++ deleting char pointer allocated with newc ++删除用new分配的char指针
【发布时间】:2020-05-10 05:31:19
【问题描述】:

在这段代码中,当第一个数字是二维数组的大小时,我从文件中获取数字。

在我的代码中我正在定义

char *filename=new char;

(我必须使用 char *filename,这是练习..) 一切正常,直到我尝试deletedeletedelete[] 都给我错误并导致我的程序崩溃。

这是我的完整代码:

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

这是我的文件的样子:

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

这是我期望得到的,但我得到了这个错误:

有谁知道这会发生什么,我可以做些什么来解决它?

【问题讨论】:

  • 您立即通过分配字符串文字filename = "text.txt"; 的地址来覆盖char *filename = new char; 持有的地址。问问自己“filename 现在指向哪里?”
  • 您正在为filename 分配一个字符。您可能需要考虑分配更多,例如 64 或 128。

标签: c++ char new-operator dynamic-memory-allocation delete-operator


【解决方案1】:

您正在尝试delete 一个char*,它没有指向分配给new 的内存。

在这一行:

char *filename = new char;

你做new 一些内存(单个char,而不是chars 的字符串)。但是在这一行:

filename = "text.txt"; 

您将char* 指针更改为指向完全不同的内存,从而泄漏了您new'ed 的内存。

然后在这一行:

delete filename;

您尝试 delete "text.txt" 文字,而不是 charnew'ed。这就是你崩溃的原因。

对于您正在尝试做的事情,您需要这样做:

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

【讨论】:

    【解决方案2】:
    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;

      【讨论】:

        【解决方案4】:

        new char 在堆上分配一个 single 字符。大多数将const char* 作为参数的函数都需要一个指向数组 的第一个元素的指针,其中空字符(\0) 作为分隔符(C 风格的字符串)。

        您甚至不能将字符串文字分配给char * 类型的变量,至少在标准C++ 中不能。您也不需要为字符串文字动态分配内存,只需使用

        const char *filename = "text.txt"; 
        

        那么你也不要删除指向字符串文字的指针。 (这很可能是导致错误的原因,您删除了指向字符串文字的指针)

        【讨论】:

        • "您甚至不能将字符串文字分配给 char * 类型的变量,至少在标准 C++ 中不能" - 您可以在 C++ 版本中在 C++11 之前。但你是对的,这不是好的做法。字符串文字应该分配给 const char*,而 C++11 和更高版本会强制执行。
        • @RemyLebeau Intersting,不知道 :)
        【解决方案5】:

        只需替换

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

        【讨论】:

          猜你喜欢
          • 2018-08-15
          • 2020-09-14
          • 1970-01-01
          • 1970-01-01
          • 2011-12-17
          • 1970-01-01
          • 2013-03-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多