首页 > 解决方案 > C - 无效指令 4

问题描述

我正在开发一个生成然后列出学校记录的应用程序。但是每次我跑步时它都会给我一个

非法指令:4

这很烦人,不会消失。我该如何解决这个问题?它让我彻夜难眠,我一直在寻找整个互联网,但找不到解决方案。

这是我正在使用的代码我认为它与数组有关

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <time.h>



struct student{
    char Name[15];
    char Grade[5];
    char Age[3];
};

void GenerateStudent(int numOfStudents){

    //Setting struct
    struct student sdv[numOfStudents];

    //Setting Defult Values
    char names[50][15] = {
        "Daniel",
        "Olivia",
        "Blair",
        "Charley",
        "Tom",
        "Jim",
        "Peter",
        "Liam",
        "Tasha",
        "Marissa",
        "Alexa",
        "Ben",
        "Kylie",
        "Jasmin",
        "Jaz",
        "Merik",
        "Nathan",
        "William",
        "Lucas",
        "Mason",
        "Logan",
        "Alexander",
        "Jack",
        "Owen",
        "James",
        "Oliver",
        "Jackson",
        "Carter",
        "Ryan",
        "Matthew",
        "Emma",
        "Ava",
        "Sophia",
        "Charlotte",
        "Emily",
        "Abigail",
        "Chloe",
        "Isabella",
        "Avery",
        "Ella",
        "Lily",
        "Amelia",
        "Hannah",
        "Sofia",
        "Grace",
        "Victoria",
        "Maya",
        "Audrey",
        "Evelyn",
        "Nolan"

    };
    char grades[5][5] = {"A","B","C","D","F"};
    int ages[] = {5,6,7,8,9,10,11,12,13,14,15,16,17};

    int nameNum,gradeNum,ageNum;

    //Getting Rand seed using time
    time_t t;

    srand((unsigned) time(&t));

    for(int i = 0;i < numOfStudents;i++){
        //Generating Rand #
        nameNum = rand() % 50 + 1;
        gradeNum = rand() % 5 + 1;
        ageNum = rand() % 13;

        //Writing Values to Array
        strcpy(sdv[i].Name, names[nameNum]);
        strcpy(sdv[i].Grade, grades[gradeNum]);
        sprintf(sdv[i].Age, "%d", ages[ageNum]);
    }

    //Make sure you make a file called student_records.txt so you get the output of this app
    FILE * fpointer = fopen("school_records.txt", "a");

    printf("Writing to file...\n");

    for(int n = 0;n < numOfStudents;n++){
        //Printing Records into the file        
        fprintf(fpointer, "Name: %s     Age: %s     Avg Grade: %s\n", sdv[n].Name,sdv[n].Age,sdv[n].Grade);
    }

    //Removing the file from memory and saving changes
    printf("Done!\n");
    fclose(fpointer);
};

void mainMenu(){
    printf("---------------Main Menu---------------\n");
    printf("█████▒▒ 1.Generate Students\n");
    printf("█████▒▒ 2.Clear Records\n");
    printf("█████▒▒ 3.Exit\n");
    printf("---------------------------------------\n");
}

void genMenu(){
    printf("-------------Generate Menu-------------\n");
    printf("Enter # of records you want to make\n");
    printf("---------------------------------------\n");
}

void cleanMenu(){
    printf("--------------Clear Menu---------------\n");
    printf("Are you sure that you want to delete\nall information from the file?\n[Y]es or [N]o\n");
    printf("-------------------------------------\n");
}


int main(){
    //Declaring Variables

    //We cant leave this one unasigned just becuase it can cause an error if the use types 0
    int recordRequests = 1;
    int i,entOption;
    int exitNum = 0;
    while(exitNum == 0){
        mainMenu();
        printf("Enter Option: ");
        scanf("%d", &entOption);

        if(entOption == 1){
            printf("\n\n\n");
            genMenu();
            printf("Enter Value: ");
            scanf("%d", &recordRequests);

            GenerateStudent(recordRequests);
        }else if(entOption == 2){
            char ans;
            int loopExit = 0;
            cleanMenu();
            printf("Enter Value: ");
            scanf("&c", ans);

            if(ans == 'Y'){
                printf("Cleaning file...\n");
                FILE * fpointer = fopen("school_records.txt", "w");
                //Printing Records into the file        
                fprintf(fpointer,"");
                //Removing the file from memory and saving changes
                fclose(fpointer);
                printf("Clean sucsessful!\nReturning to menu...\n");
                loopExit = 0;
            }else if(ans == 'N'){
                    printf("Sending back to main menu...\n\n\n");
                    loopExit = 1;
                }else{
                    printf("Invalid Option Please type Y for yes or N for no\n");
                }
            }

    }

    return 0;
}

标签: c

解决方案


我相信我能够重现您的问题。当我在我的 Microsoft 编译器上运行您的代码时,我收到“运行时检查失败 #4”,抱怨可变长度数组附近的堆栈损坏。我可以通过更改为 为终止空字符添加空格来解决此问题char Age[2];char Age[3];正如评论部分中其他几个人已经暗示的那样。

问题是以下行超出了边界访问所有三个数组:

sprintf(sdv[i].Age, "%d", ages[ageNum]);

  1. 它正在sdv越界访问数组,因为i它在范围内[0..numOfStudents],但它应该在范围内[0..numOfStudents-1]。这可以通过将行替换为 来for(int i = 0;i <= numOfStudents;i++){解决for(int i = 0;i < numOfStudents;i++){
  2. 它正在sdv[i].Age越界访问数组。该数组被声明为长度为 2 的 char 数组。但是,最大字符串长度为 3。例如,字符串"14"需要长度为 3 的 char 数组进行存储,因为它还需要空间用于终止空字符。这可以通过将学生结构声明中的行char Age[2];替换为来解决。char Age[3];
  3. 它正在ages越界访问数组,因为ageNum 在范围内[1..13],但它应该在范围内[0..12]。这是因为,在编程语言 C 中,数组索引是从 0 开始的,而其他一些编程语言的数组索引是从 1 开始的。这可以通过将行更改为ageNum = rand() % 13 + 1来解决ageNum = rand() % 13;。此外,+1出于同样的原因,必须从该行上方的两行中删除 。

最有可能的是,我所描述的 #2 导致堆栈内存损坏。但是,所有三个越界数组访问都会导致未定义的行为,因此从理论上讲,其中任何一个都可能是问题所在。

此外,您的程序包含以下错误:

在函数 main 中,您将值分配给0然后exitNum设置 for 循环条件,以便它继续下去,只要exitNum保持0。但是,您永远不会为exitNum. 因此,您实际上有一个无限循环,使您无法从主菜单退出程序。


推荐阅读