首页 > 解决方案 > 如何在 C++ 异常类析构函数中释放变量

问题描述

我正在定义一个新的 C++ 类,它的what方法返回一个char*类型,该类型具有作为构造函数传递的整数值。

最初我使用string类并从what.

然后我尝试char*在以下代码中使用类型:

/* Define the exception here */
class BadLengthException: public exception
{
  public:
    BadLengthException(int strLength)
    {
        strLen = strLength;
        res = (char*)malloc(strLength+1);
        int resultSize = sprintf(res, "%d", strLen);
    }
    ~BadLengthException() throw()
    {
        free(res);
    }
    virtual const char* what() const throw()
    {
      return res;
    }
  private:
    int strLen;
    char* res;
};

但我在释放malloc分配的变量时遇到问题:它给出了这个异常:

pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

那为什么呢?我应该在哪里以及如何释放 Exception 类中的动态分配变量?

编辑

这是一个最小的工作完整示例。该程序将要求用户输入。第一个是一个数字,指定以下输入的数量。其他输入将是字符串。如果字符串短于 5,将引发上述异常。

只需输入:1然后Me例如

#include <iostream>
#include <string>
#include <sstream>
#include <exception>
using namespace std;

/* Define the exception here */
class BadLengthException: public exception
{
  public:
    BadLengthException(int strLength)
    {
        strLen = strLength;
        res = (char*)malloc(strLength+1);
        int resultSize = sprintf(res, "%d", strLen);
    }
    ~BadLengthException() throw()
    {
        free(res);
    }
    virtual const char* what() const throw()
    {
      return res;
    }
  private:
    int strLen;
    char* res;
};



bool checkUsername(string username) {
    bool isValid = true;
    int n = username.length();
    if(n < 5) {
        throw BadLengthException(n);
    }
    for(int i = 0; i < n-1; i++) {
        if(username[i] == 'w' && username[i+1] == 'w') {
            isValid = false;
        }
    }
    return isValid;
}

int main() {
    int T; cin >> T;
    while(T--) {
        string username;
        cin >> username;
        try {
            bool isValid = checkUsername(username);
            if(isValid) {
                cout << "Valid" << '\n';
            } else {
                cout << "Invalid" << '\n';
            }
        } catch (BadLengthException e) {
            cout << "Too short: " << e.what() << '\n';
        }
    }
    return 0;
}

编辑 2

使用字符串的原始类如下:这个确实有效

class BadLengthException: public exception
{
  public:
    BadLengthException(int strLength)
    {
        res = to_string(strLength);
    }
    virtual const char* what() const throw()
    {
      return res.c_str();
    }
  private:
    string res;
};

标签: c++exceptiondestructorfreedynamic-memory-allocation

解决方案


这与异常无关。您的课程不能安全复制。

如果您要编写这样的课程,则需要使其遵循三规则

发生的事情是您的异常对象正在被复制,它复制了指针,因此您释放了两次相同的指针。

但最简单的方法是使用 astd::string而不是分配自己的内存。

class BadLengthException: public exception
{
public:
    BadLengthException(int strLength) : strLen(strLength), res(std::to_string(strLength))
    {
    }
    virtual const char* what() const throw()
    {
      return res.c_str();
    }
  private:
    int strLen;
    std::string res;
};

推荐阅读