5

这里我有一个函数,它创建一个字符串,将它分配给一个字符串指针,然后返回它。我尝试返回一个常规字符串,它工作正常。但是当我集成指针并取消引用它们时,我的程序崩溃了。当我尝试调试它时,这是我得到的消息:

Unhandled exception at 0x00024cbf in Assignment 2.exe: 0xC0000005: Access violation reading location 0xcccccce4.

这是我的代码:

string* Recipe::getCookingTime()
// @intput: none
// @output: cooking time as a string
{
    string temp;
    string displayHrs;
    string displayMins;
    if( cookingTime_->numHours < 10 ) 
        displayHrs = intToString(0) + intToString(cookingTime_->numHours );
    else 
        displayHrs = intToString(cookingTime_->numHours );
    if( cookingTime_->numMinutes < 10 ) 
        displayMins = intToString(0) + intToString(cookingTime_->numMinutes);
    else 
        displayMins = intToString(cookingTime_->numMinutes);

    temp = "The time to cook the recipe is " + displayHrs + ":" + displayMins;
    *cTime_ = temp;
    return cTime_;
}
4

3 回答 3

4

问题是您在没有实际分配内存的情况下取消引用 cTime_ 变量。我不确定这是全局变量还是成员变量,但您需要先使用“new”运算符来分配它的内存。因此,您将指向此变量(地址)的指针返回给函数的调用者,但是一旦此函数退出,它就会删除“temp”变量,因此,您返回的指针将指向无效内存。

解决方案是使用“new”运算符:

string* Recipe::getCookingTime()
// @intput: none
// @output: cooking time as a string
{
    string displayHrs;
    string displayMins;
    if( cookingTime_->numHours < 10 ) 
        displayHrs = intToString(0) + intToString(cookingTime_->numHours );
    else 
        displayHrs = intToString(cookingTime_->numHours );
    if( cookingTime_->numMinutes < 10 ) 
        displayMins = intToString(0) + intToString(cookingTime_->numMinutes);
    else 
        displayMins = intToString(cookingTime_->numMinutes);

    if( NULL == cTime_ )
    {
        cTime_ = new string();
    }

    *cTime_ = "The time to cook the recipe is " + displayHrs + ":" + displayMins;
    return cTime_;
}

但是,我必须警告您,这不是一个好的设计,因为您在这里分配内存并要求调用知道他们在完成后必须释放它。一个更好的方法是让调用者分配变量,然后传入指针:

bool Recipe::getCookingTime( string* str )
// @intput: none
// @output: cooking time as a string
{
    if( NULL == str )
    {
        // Received invalid pointer
        return false;
    }
    string displayHrs;
    string displayMins;
    if( cookingTime_->numHours < 10 ) 
        displayHrs = intToString(0) + intToString(cookingTime_->numHours );
    else 
        displayHrs = intToString(cookingTime_->numHours );
    if( cookingTime_->numMinutes < 10 ) 
        displayMins = intToString(0) + intToString(cookingTime_->numMinutes);
    else 
        displayMins = intToString(cookingTime_->numMinutes);

    *str = "The time to cook the recipe is " + displayHrs + ":" + displayMins;
    return true;
}

然后,当调用者想要使用该函数时,他们可以这样做:

cTime_ = new string();
getCookingTime( cTime_ );

总结 这里要记住的重要一点是,您必须先分配 a 指针所引用的内存,然后再尝试分配它。此外,在函数中分配内存(使用 new 运算符)而不显式删除它通常是不好的设计。分配内存的人几乎总是应该释放它的人

于 2011-03-19T03:58:55.933 回答
2
*cTime_ = temp;

看来您还没有为cTime_.

我想知道你为什么要返回指向std::string. 你为什么不简单地返回std::string如下所示:

std::string Recipe::getCookingTime()
{
   //your same code
   return temp; //this is fine!
}

请注意,返回类型的类型从 更改std::string*std::string

于 2011-03-19T03:51:36.617 回答
-2

我将只关注您的问题所在的位置,而不是代码中的其他任何地方。首先,我认为您没有发布完整的代码,因为根据您发布的内容,我看不到 cTime_ 在该方法中的定义位置,因此您的代码甚至无法编译。其次,假设您将 cTime_ 定义为指向字符串的指针,并将该指针分配给字符串 temp 占用的内存。当该方法退出时, temp 超出范围,现在 cTime_ 不再指向有效的内存位置,因此您会遇到访问冲突。你可能会考虑这样的事情:

void Recipe::getCookingTime( string& str )
{
    string displayHrs;
    string displayMins;
    if( cookingTime_->numHours < 10 ) 
        displayHrs = intToString(0) + intToString(cookingTime_->numHours );
    else 
        displayHrs = intToString(cookingTime_->numHours );
    if( cookingTime_->numMinutes < 10 ) 
        displayMins = intToString(0) + intToString(cookingTime_->numMinutes);
    else 
        displayMins = intToString(cookingTime_->numMinutes);

    str = "The time to cook the recipe is " + displayHrs + ":" + displayMins;
}

然后调用 getCookingTime():

string s;
getCookingTime(s);

您现在将处理引用,而不是处理指针。代码会更直接。

于 2011-03-19T05:09:01.930 回答