【问题标题】:2-D Array of structures -> unable to fix a segmentation fault :(二维结构数组->无法修复分段错误:(
【发布时间】:2019-12-24 19:36:43
【问题描述】:

SO(双关语)我想从 HackerEarth 解决这个问题:https://www.hackerearth.com/practice/data-structures/arrays/multi-dimensional/practice-problems/algorithm/the-wealthy-landlord/

这是我的代码:

#include <stdio.h>
#define ll long long 

int main () {
    ll int N;
    scanf("%d", &N);
    ll int i, j, a, b;
    ll int TOTAL;

    typedef struct {
        ll int flag;
        ll int count;
        // int fc[N]; // farmer cost OR cost for farmer i
        ll int *fc;
    } land;

    // check whether all of them have been
    // initialised to 0
    // printf("%d ", arr[2][2].count);
    // yes

    land arr[1000][1000];
    for(i=0; i<1000; i++) {
        for(j=0; j<1000; j++) {
            arr[i][j].fc = (ll int *)calloc(N, sizeof(ll int));
        }
    }

    ll int x1, y1, x2, y2, c;
    ll int ta, tb; // temp a // temp b
    for(i=0; i<N; i++) {
        scanf("%lld %lld %lld %lld %lld", &x1, &y1, &x2, &y2, &c);
        // the array index starts from 0
        // so to match the inputs to the correct indices
        // the inputs must be reduced by one
        for(a=x1; a<=x2; a++) {
            for (b=y1; b<=y2; b++) {
                ta = a-1;
                tb = b-1;

                arr[ta][tb].count++;
                if(arr[ta][tb].count >= 2)
                    arr[ta][tb].flag = 1;

                arr[ta][tb].fc[i] = c;
            }
        }
    }

    ll int k;
    for(i=0; i<1000; i++) {
        for(j=0; j<1000; j++) {
            if (arr[i][j].flag == 1) {
                for(k=0; k<N; k++)
                    TOTAL += arr[i][j].fc[k];
            }
        }
    }

    printf("%lld", TOTAL);
    return 0;
}

结果:运行时错误 (SIGSEGV)

编译日志: 编译成功

执行日志:执行失败。
分段错误:发生这种情况 因为导致缓冲区的超出范围的数组索引 溢出、错误初始化的指针等。信号是 当程序尝试在外部读取或写入时生成 分配给它的内存或写内存只能是 读。例如,您正在使用不支持的语言访问 a[-1] 支持数组的负索引。

我已多次编辑此代码并通过查看各种 SO 问题修复了各种问题。现在它非常接近工作,但它只是板着脸说分段错误。最糟糕的故障,几乎没有提示您应该如何修复它。我没有主意了!

另外 - 可能有更好的方法来解决这个问题,它不涉及二维结构数组中的数组,但我很想学习如何解决这个分段错误。

【问题讨论】:

  • 哪一行代码导致了段错误?
  • 对我来说,land arr[1000][1000]; 行看起来有点可疑。您要求在堆栈上创建一个大小 >= 2400 万字节的自动变量!如果这不会导致堆栈溢出,我不确定会发生什么。 (您可以尝试从 main 移出并改成 static - 这不是最好的代码,我同意,但它可能有助于诊断。)
  • 使用 MSVC (VS2019) 编译时,我收到此警告(以及其他一些警告):警告 C6262:函数使用堆栈的 '24000112' 字节:超过 /analyze:stacksize '16384 '。考虑将一些数据移动到堆中。
  • @AdrianMole 非常感谢您的反馈!至少现在我知道哪些线路导致了问题。在大学里,我们几乎没有开始使用数据结构(只完成了数组)。这意味着我对堆栈和堆一无所知嘿嘿,我应该尝试一种更简单的方法来解决问题。只是出于好奇,我很想看看这段代码在更正后会是什么样子。

标签: c arrays data-structures segmentation-fault dynamic-memory-allocation


【解决方案1】:

您的行:land arr[1000][1000];arr 声明为 自动 变量,这意味着空间是从 堆栈 分配给它的。简单地说,这个 stack 是在调用函数时分配给本地使用的内存(main 实际上只是操作系统在运行程序时调用的函数)。

通常,堆栈上的可用空间量是有限的 - 通常为 16 - 64 KB。但是,您的 arr 变量(假设 long long int 为 8 个字节,指针为 8 个字节)将需要超过 24 兆字节。这几乎肯定是导致您的“堆栈溢出”的原因!

此问题的“快速解决方案”是声明变量static。这意味着空间是在编译时(或者更可能是在链接时)分配的,并且在程序运行时被“锁定”到内存中。 (您可能会注意到执行此操作后可执行文件的大小增加了 24 MB - 取决于您的平台!)

这里是您的代码稍作修改的版本,经过此更正,以及其他一些改进建议(均标有“///”注释分隔符:

#include <stdio.h>
#include <stdlib.h>

#define ll long long 

int main() {
    ll int N;
    scanf("%lld", &N); /// The plain "%d" format expects an "int" argument - use "%lld" for "long long int"
    ll int i, j, a, b;
    ll int TOTAL = 0;  /// If you don't INITIALIZE "TOTAL" it could start off with ANY value whatsoever!

    typedef struct {
        ll int flag;
        ll int count;
        // int fc[N]; // farmer cost OR cost for farmer i
        ll int* fc;
    } land;

    // check whether all of them have been
    // initialised to 0
    // printf("%d ", arr[2][2].count);
    // yes

    static land arr[1000][1000]; /// Without "static" this array (~ 24 Megabytes) will overflow the stack!
    for (i = 0; i < 1000; i++) {
        for (j = 0; j < 1000; j++) {
            arr[i][j].fc = (ll int*)calloc(N, sizeof(ll int));
        }
    }

    ll int x1, y1, x2, y2, c;
    ll int ta, tb; // temp a // temp b
    for (i = 0; i < N; i++) {
        scanf("%lld %lld %lld %lld %lld", &x1, &y1, &x2, &y2, &c);
        // the array index starts from 0
        // so to match the inputs to the correct indices
        // the inputs must be reduced by one
        for (a = x1; a <= x2; a++) {
            for (b = y1; b <= y2; b++) {
                ta = a - 1;
                tb = b - 1;

                arr[ta][tb].count++;
                if (arr[ta][tb].count >= 2)
                    arr[ta][tb].flag = 1;

                arr[ta][tb].fc[i] = c;
            }
        }
    }

    ll int k;
    for (i = 0; i < 1000; i++) {
        for (j = 0; j < 1000; j++) {
            if (arr[i][j].flag == 1) {
                for (k = 0; k < N; k++)
                    TOTAL += arr[i][j].fc[k];
            }
        }
    }

    printf("%lld", TOTAL);
    return 0;
}

请随时要求进一步澄清和/或解释。

【讨论】:

    猜你喜欢
    • 2014-10-02
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    相关资源
    最近更新 更多