【问题标题】:Problems with dereferencing a pointer (and returning it)取消引用指针(并返回它)的问题
【发布时间】:2011-07-18 14:39:29
【问题描述】:

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

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

【问题讨论】:

  • 非常感谢您的所有回复,现在我已修复它并且它正在工作。我忘了分配内存:S。我知道这样做更容易,但我必须编写一个符合某些规范的程序。正在实现这个功能其中之一。

标签: c++ pointers string runtime-error dereference


【解决方案1】:

问题是您在没有实际分配内存的情况下取消引用 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 运算符)而不显式删除它通常是不好的设计。 分配内存的人几乎总是应该释放它的人

【讨论】:

  • 当您重新阅读问题并意识到您原来的答案是错误的,但您认为这仍然是一个好建议时,最好的办法是用&lt;strike&gt;&lt;/strike&gt; 包围它,这样它就被划掉了但仍然可读。你的第一个代码示例也是一场灾难......*string = ...string 是一种类型!
  • 关于编辑的好点,我会修复它,但我没有取消引用类型,即指向传入的字符串类型的指针。
  • 我们都可以看到您的编辑历史记录,因此承认错字并修复它比否认 cmets 中提出的问题更好。
  • 我无意忽略一个问题,我只是想让它为其他阅读它的人提供更清晰的答案。你也可以稍微尊重一点。我是论坛的新手,仍在学习标准做法。我所要做的就是学习和帮助他人。
【解决方案2】:
*cTime_ = temp;

您似乎没有为cTime_ 分配内存。

我想知道您为什么要返回指向 std::string 的指针。不如直接返回std::string,如下图:

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

注意返回类型的类型从std::string*改为std::string

【讨论】:

  • 不这样做的唯一原因是防止复制返回的字符串。 (这只是在嵌入式环境、真正密集的应用程序或相对频繁调用的函数中真正存在的问题)。
  • @drewag:现在大多数编译器都实现了RVO:en.wikipedia.org/wiki/Return_value_optimization ...另外,如果你分配内存并返回它,完成后释放内存std::string &cTime作为参数传递,并在函数中更新cTime
【解决方案3】:

我将只关注您的问题所在的位置,而不是代码中的其他任何地方。首先,我认为您没有发布完整的代码,因为根据您发布的内容,我看不到 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);

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

【讨论】:

  • 不,cTime_ 没有指向temptemp 被复制到 cTime_ 指向的任何位置(显然没有,基于错误消息)。
  • 你这样做很困难,没有充分的理由。 string s = getCookingTime(); 同样有效,如果您按值返回字符串,可能会做同样的事情。相信你的编译器!
猜你喜欢
  • 2013-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 2018-12-08
  • 2011-07-09
  • 2021-08-04
  • 1970-01-01
相关资源
最近更新 更多