C中的Segmentation fault问题(core dumped)
Segmentation fault problem in C (core dumped)
#include <stdio.h>
#include <stdlib.h>
struct arrayADT {
int *A;
int size;
int length;
int *B;
int arr3;
};
struct arrayADT * MergeArray(struct arrayADT *arr1, struct arrayADT *arr2) { //we create thus in heap cuz we need to be able to use these in main function
struct arrayADT *arr3 = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
int i, j, k;
i = j = k = 0;
while(i < arr1->length && j < arr1->length ) {
if(arr1->A[i] < arr2->A[j]) {
arr3->A[k] = arr1->A[i];
k++;
i++;
}
else {
arr3->A[k] = arr2->A[j];
k++;
j++;
}
}
for(; i<arr1->length ; i++) {
arr3->A[k] = arr1->A[i];
k++;
}
for(; j < arr2->length ; j++) {
arr3->A[k] = arr2->A[j];
k++;
}
arr3->length = arr1->length + arr2->length;
arr3->length = 10;
}
void main() {
struct arrayADT arr;
printf("Enter the size of an array");
scanf("%d", &arr.size);
arr.A = (struct arrayADT *)malloc(arr.size * sizeof(int));
arr.length = 0;
int n;
printf("enter the number of elements in an array");
scanf("%d", &n);
printf("enter the elements");
for(int i = 0; i < n; i++) {
scanf("%d", &arr.A[i]);
}
arr.length = n;
display(arr);
printf("Enter second array");
int j;
struct arrayADT *B = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
for(j = 0; j < arr.length; j++) {
scanf("%d", &B[j]);
}
struct arrayADT *arr3 = (struct arrayADT *)malloc(sizeof(struct arrayADT));
arr3 = MergeArray(&arr, &B);
display(*arr3);
我想使用堆内存合并这些数组,但出现分段错误。我是使用指针进行 C 编程的新手,我在这里感到震惊,如果我在您的帮助下通过了这个障碍,那将会非常有帮助。
而且我没有弄清楚我的错误所在如果有人也指定它会很有帮助,这样我以后就可以避免这些错误。
PS: 我正在使用 minGW 编译器。
总的来说,您的代码是无组织的。有几种未定义行为的情况,例如您没有正确扫描第二个数组。您的分段错误最有可能的候选者在这里:
struct arrayADT *arr3 = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
这会给你一块未初始化的内存。 arr3
的长度和大小可以是任何值,其数据字段 A
未指向有效内存。访问它可能会崩溃。
您的代码中包含三个数组。你一步一步地构建每一个,你对待每一个都不同。这很容易导致错误。让我们更系统地讨论这个问题。
让我们为固定大小的数组创建一个结构类型:最大大小必须在创建时给出并且不能更改。数组的实际长度可以是从 0 到其最大大小的任何值。
typedef struct Array Array;
struct Array {
int *value; // data array
int length; // actual length, 0 <= length <= size
int size; // maximum capacity
};
我们在堆上创建这样的数组,因为初始化成员容易出错,所以我们编写了一个构造函数:
Array *array_create(int size)
{
Array *array = calloc(1, sizeof(*array));
array->size = size;
array->value = calloc(size, sizeof(*array->value));
return array;
}
此函数最多为 size
个整数创建一个空数组。如果我们分配了内存,我们必须稍后释放它,所以让我们写一个相应的析构函数,它清理资源:
void array_destroy(Array *array)
{
if (array) {
free(array->value);
free(array);
}
}
数组销毁后,就不能再使用了,就像调用free()
后的内存一样。
数组一开始是空的,所以让我们写一个函数,如果有空间就在末尾添加元素:
void array_push(Array *array, int x)
{
if (array->length < array->size) {
array->value[array->length++] = x;
}
}
以及打印它的函数:
void array_print(const Array *array)
{
printf("[");
for (int i = 0; i < array->length; i++) {
if (i) printf(", ");
printf("%d", array->value[i]);
}
printf("]\n");
}
现在您可以像这样创建数组:
Array *a = array_create(10);
for (int i = 0; i < a->size; i++) {
array_push(a, i);
}
array_print(a);
array_destroy(a);
您的合并功能也会更简单。这是一个完整的例子。 (但是是使用生成的数组,而不是用户输入的数组。)
#include <stdio.h>
#include <stdlib.h>
typedef struct Array Array;
struct Array {
int *value;
int length;
int size;
};
Array *array_create(int size)
{
Array *array = calloc(1, sizeof(*array));
array->size = size;
array->value = calloc(size, sizeof(*array->value));
return array;
}
void array_destroy(Array *array)
{
if (array) {
free(array->value);
free(array);
}
}
void array_push(Array *array, int x)
{
if (array->length < array->size) {
array->value[array->length++] = x;
}
}
void array_print(const Array *array)
{
printf("[");
for (int i = 0; i < array->length; i++) {
if (i) printf(", ");
printf("%d", array->value[i]);
}
printf("]\n");
}
Array *merge(Array *a, Array *b)
{
Array *res = array_create(a->length + b->length);
int i = 0;
int j = 0;
while(i < a->length && j < b->length) {
if(a->value[i] < b->value[j]) {
array_push(res, a->value[i++]);
} else {
array_push(res, b->value[j++]);
}
}
while(i < a->length) {
array_push(res, a->value[i++]);
}
while(j < b->length) {
array_push(res, b->value[j++]);
}
return res;
}
int main(void)
{
Array *a = array_create(10);
Array *b = array_create(6);
Array *c;
for (int i = 0; i < a->size; i++) {
array_push(a, 1 + 3 * i);
}
for (int i = 0; i < b->size; i++) {
array_push(b, 4 + 2 * i);
}
array_print(a);
array_print(b);
c = merge(a, b);
array_print(c);
array_destroy(a);
array_destroy(b);
array_destroy(c);
return 0;
}
如果你已经读到这里,这里是内幕:
整理您的代码。这适用于代码布局,也适用于编写小的、普遍适用的函数,而不是“手工”完成所有事情。 (上面的数组类型有点犹豫:它使用函数,但获取数据仍然是通过访问结构字段来完成的。您甚至可以更改 szie 和长度,whixh 不应该真的发生。)
使用 -Wall
启用编译器警告。您将获得有关潜在(通常是实际)错误的有用信息。
祝你好运!
#include <stdio.h>
#include <stdlib.h>
struct arrayADT {
int *A;
int size;
int length;
int *B;
int arr3;
};
struct arrayADT * MergeArray(struct arrayADT *arr1, struct arrayADT *arr2) { //we create thus in heap cuz we need to be able to use these in main function
struct arrayADT *arr3 = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
int i, j, k;
i = j = k = 0;
while(i < arr1->length && j < arr1->length ) {
if(arr1->A[i] < arr2->A[j]) {
arr3->A[k] = arr1->A[i];
k++;
i++;
}
else {
arr3->A[k] = arr2->A[j];
k++;
j++;
}
}
for(; i<arr1->length ; i++) {
arr3->A[k] = arr1->A[i];
k++;
}
for(; j < arr2->length ; j++) {
arr3->A[k] = arr2->A[j];
k++;
}
arr3->length = arr1->length + arr2->length;
arr3->length = 10;
}
void main() {
struct arrayADT arr;
printf("Enter the size of an array");
scanf("%d", &arr.size);
arr.A = (struct arrayADT *)malloc(arr.size * sizeof(int));
arr.length = 0;
int n;
printf("enter the number of elements in an array");
scanf("%d", &n);
printf("enter the elements");
for(int i = 0; i < n; i++) {
scanf("%d", &arr.A[i]);
}
arr.length = n;
display(arr);
printf("Enter second array");
int j;
struct arrayADT *B = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
for(j = 0; j < arr.length; j++) {
scanf("%d", &B[j]);
}
struct arrayADT *arr3 = (struct arrayADT *)malloc(sizeof(struct arrayADT));
arr3 = MergeArray(&arr, &B);
display(*arr3);
我想使用堆内存合并这些数组,但出现分段错误。我是使用指针进行 C 编程的新手,我在这里感到震惊,如果我在您的帮助下通过了这个障碍,那将会非常有帮助。 而且我没有弄清楚我的错误所在如果有人也指定它会很有帮助,这样我以后就可以避免这些错误。 PS: 我正在使用 minGW 编译器。
总的来说,您的代码是无组织的。有几种未定义行为的情况,例如您没有正确扫描第二个数组。您的分段错误最有可能的候选者在这里:
struct arrayADT *arr3 = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
这会给你一块未初始化的内存。 arr3
的长度和大小可以是任何值,其数据字段 A
未指向有效内存。访问它可能会崩溃。
您的代码中包含三个数组。你一步一步地构建每一个,你对待每一个都不同。这很容易导致错误。让我们更系统地讨论这个问题。
让我们为固定大小的数组创建一个结构类型:最大大小必须在创建时给出并且不能更改。数组的实际长度可以是从 0 到其最大大小的任何值。
typedef struct Array Array;
struct Array {
int *value; // data array
int length; // actual length, 0 <= length <= size
int size; // maximum capacity
};
我们在堆上创建这样的数组,因为初始化成员容易出错,所以我们编写了一个构造函数:
Array *array_create(int size)
{
Array *array = calloc(1, sizeof(*array));
array->size = size;
array->value = calloc(size, sizeof(*array->value));
return array;
}
此函数最多为 size
个整数创建一个空数组。如果我们分配了内存,我们必须稍后释放它,所以让我们写一个相应的析构函数,它清理资源:
void array_destroy(Array *array)
{
if (array) {
free(array->value);
free(array);
}
}
数组销毁后,就不能再使用了,就像调用free()
后的内存一样。
数组一开始是空的,所以让我们写一个函数,如果有空间就在末尾添加元素:
void array_push(Array *array, int x)
{
if (array->length < array->size) {
array->value[array->length++] = x;
}
}
以及打印它的函数:
void array_print(const Array *array)
{
printf("[");
for (int i = 0; i < array->length; i++) {
if (i) printf(", ");
printf("%d", array->value[i]);
}
printf("]\n");
}
现在您可以像这样创建数组:
Array *a = array_create(10);
for (int i = 0; i < a->size; i++) {
array_push(a, i);
}
array_print(a);
array_destroy(a);
您的合并功能也会更简单。这是一个完整的例子。 (但是是使用生成的数组,而不是用户输入的数组。)
#include <stdio.h>
#include <stdlib.h>
typedef struct Array Array;
struct Array {
int *value;
int length;
int size;
};
Array *array_create(int size)
{
Array *array = calloc(1, sizeof(*array));
array->size = size;
array->value = calloc(size, sizeof(*array->value));
return array;
}
void array_destroy(Array *array)
{
if (array) {
free(array->value);
free(array);
}
}
void array_push(Array *array, int x)
{
if (array->length < array->size) {
array->value[array->length++] = x;
}
}
void array_print(const Array *array)
{
printf("[");
for (int i = 0; i < array->length; i++) {
if (i) printf(", ");
printf("%d", array->value[i]);
}
printf("]\n");
}
Array *merge(Array *a, Array *b)
{
Array *res = array_create(a->length + b->length);
int i = 0;
int j = 0;
while(i < a->length && j < b->length) {
if(a->value[i] < b->value[j]) {
array_push(res, a->value[i++]);
} else {
array_push(res, b->value[j++]);
}
}
while(i < a->length) {
array_push(res, a->value[i++]);
}
while(j < b->length) {
array_push(res, b->value[j++]);
}
return res;
}
int main(void)
{
Array *a = array_create(10);
Array *b = array_create(6);
Array *c;
for (int i = 0; i < a->size; i++) {
array_push(a, 1 + 3 * i);
}
for (int i = 0; i < b->size; i++) {
array_push(b, 4 + 2 * i);
}
array_print(a);
array_print(b);
c = merge(a, b);
array_print(c);
array_destroy(a);
array_destroy(b);
array_destroy(c);
return 0;
}
如果你已经读到这里,这里是内幕:
整理您的代码。这适用于代码布局,也适用于编写小的、普遍适用的函数,而不是“手工”完成所有事情。 (上面的数组类型有点犹豫:它使用函数,但获取数据仍然是通过访问结构字段来完成的。您甚至可以更改 szie 和长度,whixh 不应该真的发生。)
使用
-Wall
启用编译器警告。您将获得有关潜在(通常是实际)错误的有用信息。
祝你好运!