【问题标题】:Function not returning/Program exiting功能不返回/程序退出
【发布时间】:2020-07-28 20:16:37
【问题描述】:

我正在为背包问题的动态解决方案编写代码,从文件中读取值、重量等。写完背包函数代码后,我尝试只测试返回的结果时似乎不会返回。

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

using namespace std;

//knapsack here
int knapsack(int cap, int weight[], int value[], int n)
{
    int** K = new int* [n + 1];
    int j = 0;
    int l = 0;
    for (int i = 0; i < n + 1; i++)
    {
        K[i] = new int[cap + 1];
    }
    for (j = 0; j <= n; j++)
    {
        for (l = 0; l <= cap; l++)
        {
            if (j == 0 || l == 0)
                K[j][l] = 0;
            else if (weight[j - 1] <= l)
            {
                K[j][l] = max(weight[j - 1] + K[j - 1][l - weight[j - 1]], K[j - 1][l]);
            }
            else
            {
                K[j][l] = K[j - 1][l];
            }
        }
    }

    return K[j][l]; <--- Exception thrown
}

int main(void)
{
    string filename;
    ifstream infile;
    int capacity = 0;
    int items = 0;

    //Get input file from user and open

    cout << "Enter the file name: ";
    cin >> filename;

    infile.open(filename);

    //Get capacity and number of items
    infile >> capacity >> items;

    //Initialize arrays
    int* w = new int[items];
    int* v = new int[items];

    //Read values from file into arrays
    for (int i = 0; i < items; i++)
    {
        infile >> w[i];
        infile >> v[i];
    }

    //Solution Table
    cout << endl << endl << endl;
    cout << "Solution Table:" << endl;

    //Testing purposes
    cout << knapsack(capacity, w, v, items) << endl << "Test";

    infile.close();

    return 0;

}

在 main 中打印的所有内容都将打印到最后的 cout(在解决方案表:行打印之后)。然后程序将暂停片刻并退出并显示错误代码(C:\Users\Me\source\repos\Project3\Debug\Project3.exe (process 3028) exited with code -1073741819)。我还没有想出从函数中获得返回的方法,退出是我也无法弄清楚它为什么会发生的原因。

编辑:使用调试器时,在返回时通过背包函数运行时抛出异常:

在 Project3.exe 中的 0x006BB128 处引发异常:0xC0000005:访问冲突读取位置 0xFDFDFE0D

【问题讨论】:

  • 建议:停止使用 C 风格的数组,学习(并使用)std::array 和 std::vector。
  • 我和 Jesper 在一起。你迫切地需要改掉这个习惯。此函数每次运行时都会大量泄漏内存。这不是一种可持续的代码开发方式。您还需要学习如何使用简单的一维数组进行二维数组仿真。这些更容易分配,而且访问速度要快得多。
  • 当我使用调试器时,它通常会告诉我代码崩溃的确切位置。调试器非常好用!

标签: c++ algorithm knapsack-problem


【解决方案1】:

    int** K = new int* [n + 1];
    // ...
        K[i] = new int[cap + 1];
    // ...
    for (j = 0; j <= n; j++)
    {
        for (l = 0; l <= cap; l++)
        {
            // ...
        }
    }
    // j == n + 1
    // l == cap + 1
    return K[j][l]; <--- Exception thrown because of out of bounds access to K

K 是一个长度为n + 1 的数组,这意味着使用从O 到(包括)n 的索引来访问它的元素。 n + 1 是越界访问。在(外部)for 循环的末尾,变量j 是n + 1。您对内部循环和第二个operator[] 犯了同样的错误。

话虽如此,如果您这样做会很有帮助:

  • 抛弃“二维数组”的想法。这些指向数组的指针数组很难处理并且对性能有很大影响(混乱的内存位置)。它们(可能)仅在“完整”数组(例如,扁平化为单个数组的 2D 表)太大而无法可靠地成功分配时有用。

  • 使用std::vector。使用原始数组确实没有意义。除了学习。在这种情况下:delete[] 你分配的内存!

  • Why is "using namespace std;" considered bad practice?

【讨论】:

  • 向量下标超出范围与试图越过数组边界是否相同?我将它们更改为向量并删除了额外的索引,但这似乎仍然是一个问题
  • 是的,超出范围就是超出范围;当你有 5 个元素时,你无法访问/使用第六个元素。使用 std::vector::at 而不是 operator[] 可以为您提供(保证)边界检查,这可能对您的情况有所帮助
【解决方案2】:

C 风格的字符串可能会导致问题。它们很难维护和跟踪。我在这里支持 Jesper 的想法。

此外,我没有看到您在使用完会造成内存泄漏的指针后释放内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 2014-06-04
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多