簡體   English   中英

可能的 Memory 分配問題?

[英]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 設置,但程序會在同一個地方崩潰提前謝謝!

代碼 output

您想分配一個大小為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM