【问题标题】:C++ Segmentation fault after catching exception and calling cout捕获异常并调用 cout 后的 C++ 分段错误
【发布时间】:2023-03-18 20:12:01
【问题描述】:

在我的程序中,调用时出现分段错误

cout << ( ball(1,0,0) ).getName();

当我打电话时用于测试目的
( ball(1,0,0) ).getName();

我按预期得到一个异常并且程序没有崩溃。

这里可能有什么问题?我尝试重载 ostream,但似乎没有用。程序的相关部分是:

球和场::operator()(int x, int y, int z){

try{
    if (arr[x][y][z]==1){ // When it's 1, there is a ball in that coord 
        return search(root,x,y,z); // Return ball instance
    }else{

        throw ballException(); // 'Error: Ball not found'
    }
}catch(std::exception &e){
    std::cout << e.what() << std::endl;

}

}

const string& Ball::getName() const {

                try{
                    return this->name;

                }catch(std::exception & e){

                }


}

Ball::Ball(const string& name, const string& type, int size){
this->name =name;
this->type = type;
this->size= size;

}
球例外是:

 class ballException: public exception {
virtual const char* what() const throw() {
        return "Error: No Ball in the coordinates!";
}

};

【问题讨论】:

  • 好的,我已经包含了相关部分的代码
  • 你知道分段错误不是例外吗?
  • 是的,它应该打印出异常,但我在调用 std::cout 时出现分段错误
  • 如何声明名称、类型和大小?还有 BallException?

标签: c++ exception segmentation-fault cout ostream


【解决方案1】:

当你捕捉到异常时你没有返回任何东西:

Ball& Field::operator()(int x, int y, int z){
    try{
        if (arr[x][y][z]==1){ // When it's 1, there is a ball in that coord 
            return search(root,x,y,z); // Return ball instance
        }else{
            throw ballException(); // 'Error: Ball not found'
        }
    }catch(std::exception &e){
        std::cout << e.what() << std::endl;
    }
    // Nothing is returned.
}

除非search也抛出异常,否则异常处理完全没有意义,代码相当于

Ball& Field::operator()(int x, int y, int z){
    if (arr[x][y][z]==1){ // When it's 1, there is a ball in that coord 
        return search(root,x,y,z); // Return ball instance
    }
    // Returns nothing
}

在那个不存在的对象上调用 getName 可能会或可能不会起作用——它是未定义的。
(与仅引用它相比,尝试打印不存在的名称时更有可能崩溃。)

您可能希望在调用代码中处理异常,而不是使用不存在的对象呈现该代码:

Ball& Field::operator()(int x, int y, int z){
    if (arr[x][y][z]==1){
        return search(root,x,y,z);
    }else{
        throw ballException();
    }
}

【讨论】:

  • 我实际上在 search() 函数中有相同的异常处理,但是当我第一次编写该函数时,我得到了同样的错误,所以我切换回 if else one。我想知道的是,当我只调用 field(x,y,z).getName() 时,我只会得到一个异常。没有崩溃。如果问题是关于不返回任何内容,为什么当我在没有 cout 的情况下调用 field(x,y,z).getName() 时程序不会崩溃
  • @shellnut 未定义;任何事情都可能发生,包括不崩溃和按预期进行。 (如果你在search 中做同样的事情,它也有同样的问题。不要过度使用异常。)
  • 好的,在处理异常时,我分配了一个新的 Ball() 对象(指针绑定到类 Field()),从 catch 块返回它的取消引用,它似乎没有问题.但我觉得这是一个非常混乱的解决方案,所有分配,删除析构函数中的额外 Ball() 对象等,我也不能用周围的 try{}catch 块编辑调用函数。(因为作业)是有比分配一个无用的新 Ball 对象更好的解决方案吗?
  • @shellnut 是的——让异常继续到调用代码并在那里处理它。不要将异常用于本地错误处理,这不是它们的用途。
【解决方案2】:

当你捕获异常时, foo(0) 是否仍然返回一个可以调用 getName() 的对象?

要使用这样的语法,您通常必须返回一个空的(通常是静态的)对象,在该对象上实现 getName(),或者在退出函数之前确保对象的状态。下面是大意:

#include <exception>
#include <iostream>
#include <string>

class SomeObject
{
public:
    SomeObject(const std::string& name):_name(name)
    {
    }
    const std::string&  getName() const
    {
        return _name;
    };

    static const SomeObject& getEmpty()
    {
        static SomeObject _empty("");
        return _empty;
    };
private:

    std::string _name;

};


const SomeObject *function( bool throw_exception)
{
    SomeObject * NeverConstructed = 0;
    try {
        if ( throw_exception )
            throw std::runtime_error("oops");
    } catch ( const std::runtime_error& e) {
        std::cout << e.what() << std::endl;
        return &SomeObject::getEmpty();
    }

    return NeverConstructed; // will crash
}

int main(){

    std::cout << (function( true ))->getName() << std::endl;
    return 0;
}

【讨论】:

  • 感谢您的回答。我已经编辑了问题以包含相关部分的完整代码。根据您的回答,我应该在捕获异常时返回一个空 Ball 对象吗?由于这是一个家庭作业,我不应该在没有参数的情况下实现 Ball() 构造函数。创建 Ball 对象的唯一方法是通过 Ball("name","type",size) 创建它,当我尝试在 catch 块中返回 Ball 对象时,我会出错。
  • 我们需要查看整个代码,特别是构造函数。要返回 const std::string& 您需要有一个名为 name 的成员,并且必须在构造函数上使用 new 对其进行初始化。否则该行肯定会出现段错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-09
  • 1970-01-01
  • 2015-06-11
  • 2014-03-21
  • 1970-01-01
  • 2014-09-12
  • 2012-10-10
相关资源
最近更新 更多