【问题标题】:c++ Cycle cuts out randomly?c++ Cycle 随机中断?
【发布时间】:2015-11-03 12:29:42
【问题描述】:

首先我有这门课:

class Recept
{
    private:
       int serves;
       string* ingredient_name;
       int* ingredient_number;
       float difficulty;

    public:
       Recept(int a=0, string* b = NULL, float c = 0.0, int* d = NULL)
       {
          serves = a;
          ingredient_name = b;
          difficulty = c;
          ingredient_number = d;

       }

    ~Recept()
    {
        delete ingredient_name;
        delete ingredient_number;
    }
};

一个存储所有可用配方的对象:

Recept* AvailableRecipes;

这个函数用来初始化这个对象。 main() 唯一要做的就是调用这个函数。

void OpenRecipes()
{

    SetCurrentDirectory("\Recipes");
    system("dir /b > a.txt");

    ifstream filelist;
    filelist.open("a.txt");
    stringstream newstrstr;
    newstrstr << filelist.rdbuf();
    string seged = newstrstr.str();

    filelist.clear();
    filelist.seekg(0, ios::beg);

    newstrstr.str(std::string());
    AvailableRecipes = new Recept[count_words(seged)-1];

    string filename;
    int counter = 0;

    cout << "Total number of iterations needed: " << count_words(seged) << endl;

    for(int i = 0; i < count_words(seged) ; i++)
    {
        cout << "i: " << i << endl;
        filelist >> filename;

        if(filename != "a.txt")
        {
            stringstream newstrstr;
            ifstream input;

            input.open(filename.c_str());
            newstrstr << input.rdbuf();


            string seged2 = newstrstr.str();
            int ingredient_num[(count_words(seged2) - 2) / 2];
            string ingredient_name[(count_words(seged2) - 2) / 2];
            float difficulty;
            int serving;
            input.clear();
            input.seekg(0, ios::beg);

            input >> serving >> difficulty;

            int IntContain;
            string StringContain;

            for (int j = 0; j < sizeof(ingredient_num)/sizeof(ingredient_num[0]); j++)
            {
                input >> IntContain >> StringContain;
                ingredient_num[j] = IntContain;
                ingredient_name[j] = StringContain;


           }

            Recept a = Recept(serving, ingredient_name, difficulty, ingredient_num);

            AvailableRecipes[counter] = a;

           counter++;


            newstrstr.str(std::string());

            input.close();

            cout << "No error so far" << endl;


        }

    }

}

基本上这个函数应该: - 从子文件夹 /Recipes 读取文件名

-将文件名存储在同一文件夹中的“a.txt”中。

-逐个打开文件,并根据其中的文本创建一个Recipe对象。

-将Recipe对象添加到AvailableRecipes对象数组中。

问题是,由于某种原因,循环似乎是随机中断的。我想知道为什么,以及如何解决它:s

示例输出:

Total number of iterations needed: 4
i: 0
No error so far
i: 1
i: 2

Process returned -1073741819 (0xC0000005)   execution time : 1.312 s
Press any key to continue.

//在本例中,迭代 0 正在使用有效文件 (!="a.txt) ,迭代1处理的是“a.txt,迭代2是另一个有效文件。

我是菜鸟,非常喜欢,所以请善待:/ 使用 CodeBlocks,在 win64 上使用 minGW

【问题讨论】:

  • 旁注:你不遵守五法则。您不应使用原始指针,而应尽可能使用 unique_ptr 或 stl 容器(此处:vector)。
  • 您的程序的返回码表明:发生异常(错误访问)。在调试器下运行它以检查异常发生的位置。
  • 将程序编译为调试版本。它会告诉您问题发生在哪一行。 0xC0000005 表示“访问冲突”。因此,在某些时候,您的程序会从一些不应该读取的内存中读取。当使用像 AvailableRecipes[counter](Werner 所说的)这样的原始指针时,就会发生这种情况。
  • ingredient_name还有一个问题:它是一个指向字符串的指针,而Recept类只是在构造函数中复制了指针(而不是复制字符串)并删除了这个字符串在析构函数中。
  • 您正在多次删除内存。您需要遵循“三(或五)规则”或开始使用标准库中的集合。

标签: c++ arrays object for-loop cycle


【解决方案1】:

这根本不是随机的。根据您发布的代码了解: 1) 您需要在数组中存储 4 个单词。

2) 您创建一个大小为 [word_count] - 1 = 3 的数组(即索引 i 范围为 [0..2])。

3) 您的 for 循环有 4 次迭代(与 [word_count] 相同)(即遍历范围 [0..3] 内的索引)。

4) 当您尝试访问索引为3 的数组元素时,会出现访问冲突错误,因为它不存在(请记住:您的数组的最大索引为2)。这就是异常代码0xC0000005 的含义——访问冲突。

【讨论】:

  • 数组中需要存储三个单词:三个文本文件。但! a.txt也在这个文件夹中,“a.txt”包含四行:三个有效文件的名称,以及它自己的名称(a.txt),将被丢弃。这就是我创建 (word_count -1) 大小数组的原因,因为文件中的单词之一是垃圾。
  • @aurellb 我在回答中解释了整个工作流程。如果有您关心的count_words(seged) - 1 元素,为什么要循环遍历count_words(seged) 元素?我刚刚仔细查看了您的代码,我所说的仍然有效。是的,您跳过了第一个元素,但是,正因为如此,您尝试将实际值放入数组中的索引 1、2、3 处(因为您跳过了 0),而数组仅包含 3 个值可以去的地方,索引为0、1、2。注意,它没有索引3
【解决方案2】:

这两行已经有两个问题了

        Recept a = Recept(serving, ingredient_name, difficulty, ingredient_num);

        AvailableRecipes[counter] = a;

首先创建a,它存储指向局部变量ingredient_nameingredient_num 的指针。一旦离开声明它们的 if 语句,这些指针就会悬空。

然后在下一行,在AvailableRecipes 数组中创建a 的副本。现在每个指针都有两个副本。

最终,所有这些都将在Recept 的析构函数中结束,试图删除指针。它们不仅是悬空的,而且每个都有几个副本。双重错误!

【讨论】:

  • 谢谢!这解决了一切 :) 我重写了构造函数以在堆上创建数组,而不是复制指针,而是将局部变量的全部内容复制到它。
猜你喜欢
  • 1970-01-01
  • 2012-01-03
  • 2012-12-21
  • 1970-01-01
  • 1970-01-01
  • 2012-10-31
  • 1970-01-01
  • 2014-07-20
  • 1970-01-01
相关资源
最近更新 更多