【问题标题】:Segmentation fault(core dumped) error while executing code for N >= 10^7执行 N >= 10^7 的代码时出现分段错误(核心转储)错误
【发布时间】:2019-05-17 04:27:37
【问题描述】:

我正在尝试为 codeChef 的问题Bytelandian gold coins 编写代码。该代码适用于n < 10^7,但会为更高的值提供分段错误。我找了datatypes which could hold bigger numbers,但这也没有用。我当然认为我的代码没有问题,但递归树可能变得太大而编译器无法处理。这是代码。

#include <bits/stdc++.h>

using namespace std;

#define lli long long int

lli divide(lli n, lli dp[])
{
    lli ans = 0;

    if (n == 0)
        return 0;

    if (dp[n] != 0)
        return dp[n];

    lli m1 = floor(divide(n / 2, dp));
    lli m2 = floor(divide(n / 3, dp));
    lli m3 = floor(divide(n / 4, dp));
    lli sum = m1 + m2 + m3;
    ans = max(sum, n);
    dp[n] = ans;
    return ans;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t;
    cin >> t;
    while (t--) {
        lli n;
        cin >> n;
        lli dp[n + 1] = { 0 };
        lli ans = divide(n, dp);
        cout << ans << endl;
    }
}

【问题讨论】:

  • 你有没有想过计算机拥有无限的资源?
  • VLA(可变长度数组)是 C 特性,而不是合法的 C++。你溢出了堆栈。使用std::vector&lt;lli&gt;&lt;bits/stdc++.h&gt; 也不是标准标题,应该避免使用。
  • lli dp[n + 1] = {0}; -- 一行代码中的竞争性编码废话。疯狂的宏、非标准的 VLA 使用等
  • @Abhishek 任何递归函数如果不限制调用次数,最终都会耗尽堆栈空间,而 10^7 是找到该限制的好方法。
  • 网站上提到N可以达到10^9。恐怕算法层面还得做一些额外的工作

标签: c++ recursion


【解决方案1】:

我认为在这一行中,堆栈上分配了一个大数组:

lli dp[n + 1] = {0};

这可能是段错误的原因。您可能希望将其更改为 std::vector。例如:

std::vector<lli> dp(n + 1, 0);

或者,您可以将其设为静态或使用 new[] 分配它(可能所有测试只分配一次,以最大限度地减少开销,在此您需要记住使用 delete[] 正确清理它)。

【讨论】:

  • 用新的分配它 - 请不要使用new[]做广告。
  • @sbarzowski 但我仍然需要创建一个 N 维向量。我的意思是我根本不必 push_back() 但我必须将值存储在第 K 个位置的向量中,并且许多索引可能仍然是空的。简而言之,您不认为创建向量仍会占用与数组相同的空间吗?
  • @Swordfish 我认为使用new[] 一种有效的解决方法,但是它并不理想,并且在几乎任何“真实”代码库中我都会使用向量来推动.虽然这是一个 codechef 练习,所以学习各种方法来解决这个问题(甚至被一些人烧毁)是我猜的重点。我更改了答案以强调更好的解决方案。
  • @Abhishek 这与空间总量无关,而与分配方式有关。特别是使用向量会导致只在堆栈上保留指针、长度、容量以及其他类似的东西,而实际数据是在堆上分配的。
  • @sbarzowski 我认为使用 new[] 是一种有效的解决方法std::make_unique&lt;&gt;()ftw.
【解决方案2】:

正如@sbarzowski 所说,当你这样做时

lli dp[n+1] = {0}

您要求在堆栈上分配内存。在堆栈上分配内存,虽然会导致更快的访问时间,但会导致内存不足。相反,使用堆上的内存分配。 为此,您可以使用new 运算符。堆栈与堆分配的详细解释,请查看:https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/

此外,在处理要存储在一起的大量元素时,建议使用std::vectorstd::array。参考文献:Vector vs Array for large number of elements?

【讨论】:

    猜你喜欢
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 2018-04-03
    • 2014-09-30
    相关资源
    最近更新 更多