【问题标题】:Why do I have a runtime error dynamic memory allocation (heap)?为什么会出现运行时错误动态内存分配(堆)?
【发布时间】:2012-03-19 11:43:23
【问题描述】:

每次我取消注释 l70-72 时,我的程序都会发生运行时错误。这不是我第一次遇到这个特殊问题。

我创建了一个指向对象数组的指针,将该指针发送到一个函数中,尝试在 main 中执行该函数中定义的命令并得到一个运行时错误,所有这些都是在使用堆的同时进行的。该指针或数组中的指针显然会发生某些事情。

当我使用以下任何一项调用manage_Rectangle_arr(string strCommand, Rectangle * *arr, short *siArrayL) 时会发生错误:“填充数组”、“获取区域”和“空内容”(显然最后两个本质上与“填充数组”相关,因为它们需要它首先被执行才能起作用)

void manage_Rectangle_arr(string, Rectangle * *, short*);

int main()
{
    Rectangle * * arr;
    short siArrayL=1;

    manage_Rectangle_arr("make array", arr, &siArrayL);
    manage_Rectangle_arr("fill array", arr, &siArrayL); //Problem here
    manage_Rectangle_arr("get areas", arr, &siArrayL); //Problem here
    manage_Rectangle_arr("empty contents", arr, &siArrayL); //Problem here
    manage_Rectangle_arr("delete array", arr, &siArrayL);
}

void manage_Rectangle_arr(string strCommand, Rectangle * *arr, short *siArrayL)
{
    if(strCommand=="make array")
    arr = new Rectangle * [ *siArrayL];

    if(strCommand=="fill array") //Problem here
    for(short s=0; s< *siArrayL; ++s)
    arr[s]= new Rectangle(1, 1);

    if(strCommand=="get areas") //Problem here
    for(short s=0; s< *siArrayL; ++s)
    cout << arr[s]->getArea();

    if(strCommand=="empty contents") //Problem here
    for(short s=0; s< *siArrayL; ++s)
    delete arr[s];

    if(strCommand=="delete array")
    delete [] arr;
}

//When I call manage_Rectangle_arr(string strCommand, Rectangle * *arr, short *siArrayL) with any of the following: "fill array", "get areas" and "empty contents" (obviously the last two are related to "fill array" in nature, since they need it to be executed first in order to function)

Full C++ Source Code

【问题讨论】:

  • 如果您将演示问题的最少代码编辑到问题中,那么这个问题可以迁移到 Stack Overflow。在目前的状态下,我不会让它被迁移。
  • 你没有抓住重点。将代码包含在问题中,而不是作为外部网站的链接。
  • 我测试了你的代码。使用 Visual Studio 2010 时,代码会在 delete 未注释的情况下崩溃。这是因为您尝试删除未分配的内存区域。
  • 因为你已经添加了代码,我觉得现在迁移到 SO 已经足够好了。你应该在那里得到更好的答案。

标签: c++ function memory memory-management heap-memory


【解决方案1】:

从根本上说,这段代码有两个问题,除了 Max 指出的按值调用问题。

第一个错误是你没有正确使用函数,并且滥用字符串来给出命令。

第二个错误是you are using pointers。每门 C++ 课程都犯了这个错误。大多数 C++ 代码中没有指针。不要养成坏习惯。

更正并简化后,代码应如下所示:

int main()
{
    short siArrayL=1;
    std::vector<Rectangle> arr(siArrayL);

    fill_array(arr);
    print_areas(arr);
}

两种方法:

void fill_array(std::vector<Rectangle>& arr) {
    for (std::vector<Rectangle>::iterator i = arr.begin(); i != arr.end(); ++i)
        *i = Rectangle(1, 1);
}

void print_areas(std::vector<Rectangle> const& arr) {
    for (std::vector<Rectangle>::const_iterator i = arr.begin(); i != arr.end(); ++i)
        std::cout << i->getArea();
}

请特别注意“空内容”和“删除数组”如何不再使用。不使用指针只有两个好处。

【讨论】:

  • 好吧,那我猜我们的导师都是白痴。想了那么多。 ;) 我的理念是:代码越干净,代码就越好。这就是为什么我不是基于 LISP 的语言的忠实粉丝(很难阅读)。谢谢,康拉德,我会详细研究你的答案。现在,由于所有的指针,我的头很痛。 :(
  • @CrawlingPastaHellion 那个“字符串查找”是你教授的主意吗?
  • 公平地说,有时辅导练习可能是人为的,因为导师试图让您理解问题。它不是“真实世界”的代码解决方案。 如果这是为了强制理解指针,那么这个答案会得到 F。(即使我会像工作中的答案那样写它)。
  • @gbjbaanb 如果这是为了强制理解指针,那么讲师已经失败了。对于指针来说,这根本就不是一个合法的情况,而且我对此越来越直言不讳,因为 C++ 中如此多的垃圾代码是由指针的使用引起的。
  • @Max 如果“字符串查找”的意思是“toString”,那么书面课程中明确教授了该内容(并且在该特定作业中被要求,即使它不是必需的),所以是的,如果您指的是“toString”数据成员。
【解决方案2】:

尽管这似乎得到了很多反对意见,但我会尽力提供一个有用的答案。 :)

您的数组是Rectangle** 类型 - 即指向矩形指针的指针。您按值将其发送到方法中。这意味着您原始方法中的arr 的值将被复制到manage_Rectangle_arr 中的变量arr 中。因此,当您为 arr 分配一个值(new 内存区域/数组的地址)时,arr 将仅在被调用函数中包含该值 - 因为它们是完全不同的变量。

如果您改为将 manage_Rectangle_arr 声明为

void manage_Rectangle_arr(string strCommand, Rectangle * * &arr, short *siArrayL)

该变量/内存区域将通过引用发送,这意味着它将是另一个自动的间接级别。您可以通过使用 Rectangle*** 类型的变量并取消引用变量 arr 来完成此操作,但这很快就会变得愚蠢。

您的代码中还有许多其他“非最佳实践”,但我不会在这里全部讨论。 :) 希望这能帮助您重回正轨!

【讨论】:

  • 嗯,我不喜欢通过引用调用,有什么方法可以通过指针调用来使其工作? P.S.:通过引用调用确实有效。
  • 我会尝试三星级的方法,三星级的干邑通常比双星级和单星级的要好;)
  • @CrawlingPastaHellion 来吧,如果你自己弄清楚比让我告诉你更好......只要你不只是在源代码中随机交换符号:) 试着合并address-of 运算符。提示:您不需要在任何地方都将其声明为三星级;)
猜你喜欢
  • 1970-01-01
  • 2017-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
相关资源
最近更新 更多