2011-03-19 35 views
4

这里我有一个函数创建一个字符串,将其指定给一个字符串指针并将其返回。我试着返回一个普通的字符串,它工作正常,但是当我集成指针并引用它们时,我的程序崩溃了。当我试图调试它,这是我得到的消息:在分配2.exe在0x00024cbf取消引用指针(并返回它)的问题

未处理的异常:0000005:访问冲突读取位置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_; 
} 

希望有人可以帮助我,谢谢!

+0

非常感谢你所有的回应,现在我修好了它,它正在工作。我忘了分配内存:S。 我知道做这件事很容易,但我必须编写一个符合某些规格的程序。正在实现这个功能之一。 – Oniros 2011-03-19 06:51:05

回答

3

问题在于,如果不先实际分配内存,则会取消引用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_); 

摘要 这里要记住的重要一点是,您必须在尝试分配指针之前分配指针正在引用的内存。另外,在函数中分配内存(使用新的操作符)通常是不好的设计,而不是明确地删除它。 分配内存的人应该几乎总是释放内存的人

+0

当你重读这个问题并且意识到你的原始答案是错误的,但是你认为这仍然是一个好建议时,最好的办法是用''和''将它包围起来,这样它就会被删除,但仍然可读。你的第一个代码示例也是一场灾难...''* string = ...'? 'string'是一种类型! – 2011-03-19 05:20:10

+0

关于编辑的好处,我会解决它,但我不是取消引用类型,这是一个指向传入的字符串类型的指针。 – drewag 2011-03-19 15:14:18

+0

我们都可以看到您的编辑历史,所以它使您看起来更好承认错字并修正它,而不是否认评论中提出的问题。 – 2011-03-19 16:12:59

2
*cTime_ = temp; 

看来你还没有分配内存cTime_

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

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

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

+0

不这样做的唯一原因是为了防止复制发生的返回字符串。 (这只是嵌入式环境中的一个真正的问题,是一个真正密集的应用程序,或者是一个相对频繁调用的函数)。 – drewag 2011-03-19 04:01:25

+0

@drewag:现在大多数编译器都实现了RVO:http://en.wikipedia.org/wiki/Return_value_optimization ...除此之外,如果你分配内存并返回它,并在完成之后释放内存<<这种方法也需要时间。有一件事可以做,可以传递'std :: string&cTime'作为参数,并更新函数中的'cTime'! – Nawaz 2011-03-19 04:06:37

+0

我不知道RVO,感谢您的信息! – drewag 2011-03-19 04:09:48

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

处理指针相反的,你现在会处理的参考。代码会更直接。

+0

不,'cTime_'没有指向'temp'。 'temp'被复制到'cTime_'点(根据错误信息显然无处)。 – 2011-03-19 05:20:54

+0

你这样做很难,因为没有很好的理由。 'string s = getCookingTime();'同样有效,如果按值返回字符串,可能会做同样的事情。相信你的编译器! – 2011-03-19 06:04:22