[英]Possible Memory Allocation Issue?
G'day Coders,我為 Uni 編寫的代碼遇到了一些問題,我正在尋找一些建議。 似乎沒有經過整個 for 循環就把我吐出來了,我只能到學生 3。任何幫助將不勝感激。
#include<stdio.h>
#include <stdlib.h>//for the malloc function
int main()
{
int num;//user input of number of students
printf("enter the number of students: ");
scanf("%d",&num);
//user input of number of subjects
int subjects;
printf("enter the number of subjects: ");
scanf("%d",&subjects);
int *ptr, **arr;
//making 2d dynamic array of size nX subjects with the help of malloc
int len = sizeof(int *) * num + sizeof(int) * subjects * num;
arr = (int **)malloc(len);//will allocate the memory of size len dynamically
ptr = (int *)(arr + num);
int sum=0;//total sum of marks of a student
float average;//average of marks
//iterating for each student
for(int i=0;i<num;i++)
{
//user input the marks of each subject from a user
printf("enter the marks of student %d: ",i+1);
for(int j=0;j<subjects;j++)
scanf("%d",&arr[i][j]);
//summing up the total marks of the student
for(int j=0;j<subjects;j++)//iterating for each subject
sum+=arr[i][j];
printf("the total marks of student %d is %d \n",i+1,sum);//printing the total marks
//average of the marks of the student
average=(float)sum/(float)subjects;//average is equal to total sum divided by the total subjects
printf("and the average is %0.2f \n",average);
//making sum and average again 0 for the next student
sum=0;
average=0;
}
return 0;
}
嘗試將 gcc -Wl,--stack=268435456 -Wl,--heap=268435456 添加到 linker 設置,但程序會在同一個地方崩潰提前謝謝!
您想分配一個大小為nxm
的二維數組。 您向用戶詢問尺寸。 然后分配 memory 的數量。
但不幸的是,編譯器不知道這些維度和尋址,因為studentArray[i][j]
將失敗:第i
行有多長?
在這種情況下,您必須明確地將尋址寫為
studentArray[i*subjects+j]
Paul Ogilvie 的回答直接解決了核心問題——您實際上是在使用扁平化為 1D 的 2D 數組,因此您可以使用[i * w + j]
對其進行索引。
但是,如果您所做的只是一次計算每個學生的總和和平均值,那么您甚至根本不需要 arrays,因為您只需將分數累加到sum
中,然后除以計數。 假設您的代碼的另一個版本確實需要數組,但是,這里有一個稍微更干凈的代碼版本,它將事物分為輸入階段和輸出/計算階段。
#include <stdio.h>
#include <stdlib.h>
int main() {
int students, subjects;
printf("enter the number of students: ");
scanf("%d", &students);
printf("enter the number of subjects: ");
scanf("%d", &subjects);
// TODO: add bounds checks for students / subjects
// Allocate memory for students X subjects integers;
// calloc ensures the memory is zeroed too.
int *marks = calloc(students * subjects, sizeof(int));
// TODO: check the marks allocation succeeded
for (int i = 0; i < students; i++) {
printf("enter the marks of student %d: ", i + 1);
for (int j = 0; j < subjects; j++) {
scanf("%d", &marks[i * subjects + j]);
}
}
for (int i = 0; i < students; i++) {
int sum = 0;
printf("Student %d: ", i + 1);
for (int j = 0; j < subjects; j++) {
int mark = marks[i * subjects + j];
printf("%d ", mark);
sum += mark;
}
printf(" - ");
float average = sum / subjects;
printf("Total: %d, average: %.2f\n", sum, average);
}
return 0;
}
您的另一個選擇是在您首先分配numberOfStudents
指針的地方分配指向int
的指針,然后循環並分配一個numberofSubjects
int
塊,並依次將起始地址分配給每個分配的指針。 這是您將用於分配字符串或結構等集合的兩步分配。您可以在其中模擬2D 數組。 這看起來像您前進的方向。
為此,您必須首先分配(並驗證)您的指針塊,為每個學生分配一個指針:
/* allocate numberOfStudents pointers */
studentArray = malloc (numberOfStudents * sizeof *studentArray);
if (studentArray == NULL) { //check if memory allocated successfully
perror ("malloc-studentArray pointers");
return 1;
}
接下來,在您收集數據的循環中,您分配一個numberofSubjects
整數塊並將起始地址分配給您的下一個打開指針,例如
for (i = 0; i < numberOfStudents; i++) {
studentArray[i] = malloc (numberofSubjects * sizeof *studentArray[i]);
if (!studentArray[i]) {
perror ("malloc-studentArray[i]");
return 1;
}
printf ("enter the marks of student %d: ", i + 1);
for (j = 0; j < numberofSubjects; j++) {
scanf ("%d", &studentArray[i][j]);
sum += studentArray[i][j];
totalMarks += studentArray[i][j];
}
總而言之,您將擁有:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int numberOfStudents, numberofSubjects, sum = 0, i, j, totalMarks = 0;
int **studentArray;
printf ("Enter the Number of Students and Number of Subjects: ");
scanf ("%d%d", &numberOfStudents, &numberofSubjects);
/* allocate numberOfStudents pointers */
studentArray = malloc (numberOfStudents * sizeof *studentArray);
if (studentArray == NULL) { //check if memory allocated successfully
perror ("malloc-studentArray pointers");
return 1;
}
for (i = 0; i < numberOfStudents; i++) {
studentArray[i] = malloc (numberofSubjects * sizeof *studentArray[i]);
if (!studentArray[i]) {
perror ("malloc-studentArray[i]");
return 1;
}
printf ("enter the marks of student %d: ", i + 1);
for (j = 0; j < numberofSubjects; j++) {
scanf ("%d", &studentArray[i][j]);
sum += studentArray[i][j];
totalMarks += studentArray[i][j];
}
float average = (float)sum / numberofSubjects;
printf ("The average for student %d is %0.2f \n", j + 1, average);
average = 0;
sum = 0;
}
printf ("The Total Marks of Students is %d \n", totalMarks);
for (i = 0; i < numberOfStudents; i++)
free (studentArray[i]); /* free block of integers */
free (studentArray); /* free pointers */
}
(注意:由於這是一個 2 步分配,它需要一個 2 步free()
。當你處理完整數后,循環並free (studentArray[i]);
這將釋放所有 integer 存儲。最后一個步驟是釋放分配的指針,例如free (studentArray);
示例使用/輸出
$ ./bin/ptrissue
Enter the Number of Students and Number of Subjects: 3 4
enter the marks of student 1: 91 82 81 78
The average for student 5 is 83.00
enter the marks of student 2: 94 92 96 88
The average for student 5 is 92.50
enter the marks of student 3: 81 79 73 84
The average for student 5 is 79.25
The Total Marks of Students is 1019
請注意,您只需要將除法的一部分轉換為(float)
,分子或分母都可以。
Memory 使用/錯誤檢查
在您編寫的任何動態分配 memory 的代碼中,對於分配的 memory 的任何塊,您有兩個責任:(1)始終保留指向 ZCD69B4957F06CD818D7BF3D21980 塊的起始地址的指針,所以它可以被釋放,更需要。
您必須使用 memory 錯誤檢查程序,以確保您不會嘗試訪問 memory 或寫入超出/超出分配塊的邊界,嘗試讀取或基於未初始化值的條件跳轉,最后確認釋放所有已分配的 memory。
對於 Linux valgrind
是正常的選擇。 每個平台都有類似的 memory 檢查器。 它們都易於使用,只需通過它運行您的程序即可。
$ valgrind ./bin/ptrissue
==14645== Memcheck, a memory error detector
==14645== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14645== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==14645== Command: ./bin/ptrissue
==14645==
Enter the Number of Students and Number of Subjects: 3 4
enter the marks of student 1: 91 82 81 78
The average for student 5 is 83.00
enter the marks of student 2: 94 92 96 88
The average for student 5 is 92.50
enter the marks of student 3: 81 79 73 84
The average for student 5 is 79.25
The Total Marks of Students is 1019
==14645==
==14645== HEAP SUMMARY:
==14645== in use at exit: 0 bytes in 0 blocks
==14645== total heap usage: 6 allocs, 6 frees, 2,120 bytes allocated
==14645==
==14645== All heap blocks were freed -- no leaks are possible
==14645==
==14645== For counts of detected and suppressed errors, rerun with: -v
==14645== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始終確認您已釋放所有已分配的 memory 並且沒有 memory 錯誤。
如果您還有其他問題,請仔細查看並告訴我。
您的代碼混合了一個簡單的 2D 數組分配,稍后將作為arr[j + i * numberOfSubjects]
訪問,以及一個 2 級指針數組和數據數組。
后者的防彈方法是分配2個arrays,一個用於指針,一個用於數據,並初始化指針數組以正確使用二維數據數組:
int **arr = malloc(numberOfStudends * sizeof(int*));
int *data = malloc(numberOfStudents * numberOfSubjects * sizeof(int));
for(i=0; i<numberOfStudents; i++) {
arr[i] = data + i * numberOfSubjects;
}
您現在可以安全地使用arr[i][j]
...
一種相當先進(但不太健壯)的方法是一次分配兩個數組。 問題是,除非您確定實現對於int
沒有比int *
更嚴格的 alignment,否則這是災難的根源,我不確定它是否真的符合標准:
int **arr = malloc(numberOfStudends * sizeof(int*)
+ numberOfStudents * numberOfSubjects * sizeof(int))
int *data = (int *)(arr + numberOfStudents);
它曾經是一個常見的習慣用法,它是您的初始代碼包含的內容,但除非您有非常充分的理由這樣做,否則我建議您使用單獨的分配。
為什么不使用“[]”而不是“**”;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.