【问题标题】:C SegFault fixed by print?C SegFault 通过打印修复?
【发布时间】:2021-07-22 14:11:30
【问题描述】:

我的任务是用 C 编写一个程序。该程序应该能够检查参数并创建与我提供的参数一样大的数组。我必须用随机数填充数组。到目前为止工作正常。后来我的任务是使用指针对数组进行排序。第一件事是我不太明白指针是如何工作的,但到目前为止我已经完成了排序工作。唯一的问题是,我只能排序到 4 的大小。如果我的参数大于 4,我会排序前 4 个数字,然后是分段错误。我找不到问题,但有趣的是,如果我添加一个 printf 只是为了再次打印我的参数,它适用于我想要的任何参数!不知道怎么回事!

这里又是确切的任务,因为我觉得我描述得不太好:

为此,创建一个相同大小的动态指针字段,并使用指向 int 字段元素的指针对其进行初始化。排序时,现在应该对指针进行排序,以便第一个指针指向最小的 int 值,第二个指向下一个最大值,依此类推。

int main(int argc, char *argv[]) {
    
    int *array;
    int **arrpointer;
    
    int size = atoi(argv[1]);
     
    if (size == 0) {
        fprintf(stderr, "Wrong parameter!\n");
        return EXIT_FAILURE;
    }

    //printf("Array-Size : ");   //First I had it with scanf, which works perfectly fine without a print
    //scanf("%d", &size);

    printf("Input%d", size);  //This is the print I need somehow!

    // allocate memory
    array = (int *)malloc(size * sizeof(int));        // Init Array
    arrpointer = (int **)malloc(size * sizeof(int));  // Init Pointer Array

    //Check Pointer array 
    if (arrpointer != NULL) {
        printf("Memory allocated\n\n");
    } else {
        fprintf(stderr, "\nNo free memory.\n");
        return EXIT_FAILURE;
    }
    
    if (array != NULL) {
        printf("Memory is allocated\n\n");

        //Fill Array
        for (int i = 0; i < size; i++) {
            array[i] = rand() % 1000; //I know it is not random right now, will add later
            int *temp = &array[i];
            arrpointer[i] = temp;     //Pointer fill
        } 
    } else {
        fprintf(stderr, "\nNo free memory to allocate.\n");
        return EXIT_FAILURE;
    }
    shakersort(arrpointer, size);  //Function to sort pointers
    zeigeFeld(arrpointer, size);  //Function to Print
        
    free(array);
    free(arrpointer);
    return EXIT_SUCCESS;
} 

我知道这有点令人困惑,我很抱歉。 我还将在下面排序的地方添加代码。

void swap(int **a, int **b) {

    int ram;
    ram = **a;
    **a = **b;
    **b = ram;
}

void shakersort(int **a, int n) {
    int p, i;
    for (p = 1; p <= n / 2; p++) {
        for (i = p - 1; i < n - p; i++)
            if (*a[i] > *a[i+1]) {
                swap(&a[i], &a[i + 1]);
            }
           
        for (i = n - p - 1; i >= p; i--)
            if (*a[i] < *a[i-1]) {
                swap(&a[i], &a[i - 1]);                
            }           
    }
}

这是我尝试为指针构建的代码,到目前为止它运行良好。

我希望有人可以帮助或提供一些意见,说明我的打印解决问题的原因。我真的不明白! 感谢您的时间和帮助,如果我应该添加任何内容,请告诉我!

【问题讨论】:

  • 我想到了两件事:首先,arrpointer 应该用arrpointer = (int **) malloc(size * sizeof(int*)); 初始化。您应该使用 int 指针的大小,而不是 int 的大小。其次,据我了解,您的任务不是对实际的 int 数组进行排序(您要做什么),而是对 pointer arrary 进行排序,以使原始 int 数组保持不变,但指针您的 arrpointer 已排序。
  • 另外,您应该再次查看您发布的 sn-ps:在第一个中,最后一个大括号应该在 return EXIT_FAILURE; 之后,而不是在 and。在第二个中,您的交换方法的签名丢失了。如果你纠正了这个会更容易理解:)
  • @Kebberling Instead 的不需要的演员和潜在的类型不匹配,arrpointer = malloc(sizeof *arrpointer * size); 更容易正确编码、审查和维护。
  • 你是对的,不知道那个语法
  • @snakezz array = (int *) malloc(size * sizeof(int)); 今天还可以,但比array = malloc(sizeof *array * size); 更难审查。以后如果代码变成long long *arraysizeof(int) 就会出错。使用array = malloc(sizeof *array * size); 是正确的今天和该类型更新之后。 array = (int *) malloc(size * sizeof(int));WET

标签: c pointers segmentation-fault


【解决方案1】:

程序有未定义的行为,因为数组的分配大小不正确:

arrpointer = (int **)malloc(size * sizeof(int));

size 整数分配空间,但它应该为size 指向int 的指针分配空间,这在64 位系统上大于int。改用这个:

arrpointer = (int **)malloc(size * sizeof(int *));

或者使用目标指针的类型:

arrpointer = malloc(sizeof(*arrpointer) * size);

后一种语法更安全,因为它适用于任何非void 指针类型。

但是请注意,这个指针数组对于您的目的来说是多余的。你应该只在int的数组上实现排序函数:

void swap(int *a, int *b) {
    int ram = *a;
    *a = *b;
    *b = ram;
}

void shakersort(int *a, int n) {
    int p, i;
    for (p = 1; p <= n / 2; p++) {
        for (i = p - 1; i < n - p; i++) {
            if (a[i] > a[i + 1]) {
                swap(&a[i], &a[i + 1]);
            }
        }
        for (i = n - p - 1; i >= p; i--) {
            if (a[i] < a[i - 1]) {
                swap(&a[i], &a[i - 1]);                
            }
        }          
    }
}

我不清楚上面的代码是否真的对数组进行排序,我从不使用shakersort。

【讨论】:

  • 感谢您的解释!将从现在开始检查一切是否正常并尝试您的解决方案!
  • 次要:size * sizeof(*arrpointer) 在有/没有() 的情况下都能正常工作 - 风格问题。它也和sizeof(*arrpointer) * size 一样有效,因为乘法是可以交流的。然而,使用size_t 而不是int 引导计算有助于更复杂的计算,例如size_t * int * int,不会溢出,而int * int * size_t 可能会溢出int * int 部分。
  • 仅供参考,您主要使用什么排序算法?我知道,这太过分了,如果我的教授不想让我这样做,我绝不会那样做!在什么情况下我会使用这样的东西?你有我的例子吗?
  • @chux-ReinstateMonica:关于潜在的溢出问题,我 100% 同意你的观点,但我更喜欢在表达式不重要时使用额外的括号,特别是当它涉及 * 时解引用运算符和乘法运算符。我的风格选择是在二元运算符周围而不是在一元运算符和它们的操作数之间插入空格:sizeof *arrpointer 违反了这条规则,sizeof*arrpointer 看起来很糟糕,sizeof(*arrpointer) 是一个非常常见的习语,但不会违反我的规则。
  • @snakezz:我使用mergesort 或C 库qsort,它可能使用修改版的快速排序或其他东西。 mergesort 是稳定的,这可能是一个要求。如果排序阶段是性能瓶颈,TimSort 可能是更好的方法或专门的算法,例如整数的基数排序。
【解决方案2】:

为什么在 printf 之前使用指针? 首先你需要知道指针是什么: 指针是某种变量,其中包含另一个变量的地址。

例如:

int b = 2;

int * a = &b;

a 变量包含变量 b 的地址。那么如果你打印 ((a)) 它会给你十六进制数,它是 b 的地址。如果您打印 ((*a)),编译器将打印变量 a 的地址中的内容,并打印单元格 b 的地址中的数字数量(即 2)。

现在我猜你明白指针是什么了,再看看你的代码并纠正错误。

【讨论】:

  • 我猜 printf 周围的星星不是指针,而是使用 markdown 语法突出可疑段落的误导尝试
  • 我试图突出显示那行代码,将其删除。谢谢你的解释,有知识再看一遍!
【解决方案3】:

我更新了我的代码

arrpointer = (int **) malloc(size * sizeof(int));

arrpointer = malloc(sizeof *arrpointer * size);

而且效果很好! 谢谢大家的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 2019-11-08
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多