簡體   English   中英

C++ - 在統計分配的數組中打印對象導致分段錯誤

[英]C++ - printing objects in statistically allocated array causes segmentation fault

因此,我正在創建一個程序,該程序實現了代表一所學校及其學生和課程的多個類。 當我嘗試打印出 studentCoursePairs[] 數組中的所有 Taken 對象時,我遇到了分段錯誤,該數組表示參加特定課程的 Student 對象。 我認為我的分段錯誤來自 School.cc 中的 addTaken() 函數,它的工作是找到具有給定學生號和課程 ID 的學生對象和課程對象,然后使用找到的學生和課程創建一個新的 Taken 對象對象和等級。 然后我嘗試將這個新對象添加到 Taken 集合的后面,即 studentCoursePairs。

當我注釋掉 studentCoursePairs[i]->print() 時,分段錯誤消失了。 我不確定我做錯了什么,希望得到一些幫助。

我不確定是否需要除 School.cc 之外的其他課程,但我還是將它們包括在內以幫助理解。

學校.cc:

#include <iostream>
#include <iomanip>
using namespace std;
#include <string.h> 

#include "School.h"

School::School(string s1) : name(s1){ 
    numTaken = 0;
}

void School::addTaken(string number, int code, string grade){
    Student* s = nullptr;
    Course* c = nullptr;
    for(int i = 0; i < numTaken; ++i){
        if((studentsCollection->find(number, &s)) && (coursesCollection->find(code, &c))){
        Taken* taken = new Taken(s, c, grade);
          studentCoursePairs[i] = taken;            
          ++numTaken;
        }
    }
}

void School::printTaken(){
    cout << name << " === TAKEN: "<< endl;
    for(int i = 0; i < sizeof(studentCoursePairs)/sizeof(studentCoursePairs[0]); ++i){
        studentCoursePairs[i]->print(); //seg fault
    }   
}

附加文件:

學生收藏.cc

bool StudentCollection::find(string num, Student** s){
    for(int i = 0; i < size; ++i){
        if(students[i]->getNumber() == num){ //find student number
            *s = students[i];
        }
    }
}

CoursesCollection.cc

bool CoursesCollection::find(int id, Course** c){
    for(int i = 0; i < numCourses; ++i){
        if(courses[i]->getId() == id){ //find course id
            *c = courses[i];
        }
    }
}

我還有一個 Student 類和 Course 類,它們只是聲明和初始化信息,如學生的姓名、程序、gpa 以及課程代碼、講師、姓名、課程年份。

您的 School 對象有兩個主要問題。 讓我們從您在問題中發布的內容開始:

void School::printTaken(){
    cout << name << " === TAKEN: "<< endl;
    for(int i = 0; i < sizeof(studentCoursePairs)/sizeof(studentCoursePairs[0]); ++i){
        studentCoursePairs[i]->print(); //seg fault
    }   
}

這個 for 循環將始終運行 MAX_PAIRS 次,因為這個變量被定義為

Taken* studentCoursePairs[MAX_PAIRS];

所以sizeof(studentCoursePairs) === MAX_PAIRS * sizeof(studentCoursePairs[0])

相反,您只想遍歷實際包含有效指針的前幾個插槽。 你有一個變量: numTaken 因此,將條件更改為i < numTaken並且您的打印循環將起作用。

第二個主要問題是addTaken

void School::addTaken(string number, int code, string grade){
    Student* s = nullptr;
    Course* c = nullptr;
    for(int i = 0; i < numTaken; ++i){
        if((studentsCollection->find(number, &s)) && (coursesCollection->find(code, &c))){
        Taken* taken = new Taken(s, c, grade);
          studentCoursePairs[i] = taken;            
          ++numTaken;
        }
    }
}

讓我們玩電腦,看看如果傳入的數字和代碼有效會發生什么:

  • 如果 numTaken 為 0,則循環立即停止(因為0 < 0為假)並且 numTaken 不遞增。 您可以addTaken地調用addTaken ,它永遠不會改變numTaken
  • 假設你解決了這個問題,讓我們假設 numTaken = 5。在第一次迭代中,你檢查條件並同意這是一個有效的數字代碼組合。 因此,您創建了一個新的 Taken 對象並用新對象覆蓋studentCoursePairs[0] 在第二次迭代中,您執行相同操作並使用等效對象覆蓋studentCoursePairs[1]

這可能不是預期的行為。 相反,您可能希望在studentCoursePairs[numTaken]放置一個新對象並碰撞numTaken

void School::addTaken(string number, int code, string grade){
    Student* s = nullptr;
    Course* c = nullptr;
    if((studentsCollection->find(number, &s)) && (coursesCollection->find(code, &c))){
        Taken* taken = new Taken(s, c, grade);
        studentCoursePairs[numTaken] = taken;            
        ++numTaken;
    }
}

弄清楚如何處理傳遞的組合無效或超過 MAX_PAIRS 組合的情況留給您作為練習。

編輯:您的 CoursesCollection 中存在第三個主要問題:您為一個對象new Course()分配空間,同時將其視為數組,並將結果存儲在局部變量而不是成員中。 您的構造函數可能看起來像:

CoursesCollection::CoursesCollection(){
    courses = new Course*[MAX_COURSES];
    numCourses = 0;
}

或者,使用成員初始值設定項列表:

CoursesCollection::CoursesCollection() 
  : courses(new Course*[MAX_COURSES]), numCourses(0) {}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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