c - 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;
}
解决方案
我相信我能够重现您的问题。当我在我的 Microsoft 编译器上运行您的代码时,我收到“运行时检查失败 #4”,抱怨可变长度数组附近的堆栈损坏。我可以通过更改为 为终止空字符添加空格来解决此问题char Age[2];
,char Age[3];
正如评论部分中其他几个人已经暗示的那样。
问题是以下行超出了边界访问所有三个数组:
sprintf(sdv[i].Age, "%d", ages[ageNum]);
- 它正在
sdv
越界访问数组,因为i
它在范围内[0..numOfStudents]
,但它应该在范围内[0..numOfStudents-1]
。这可以通过将行替换为 来for(int i = 0;i <= numOfStudents;i++){
解决for(int i = 0;i < numOfStudents;i++){
。 - 它正在
sdv[i].Age
越界访问数组。该数组被声明为长度为 2 的 char 数组。但是,最大字符串长度为 3。例如,字符串"14"
需要长度为 3 的 char 数组进行存储,因为它还需要空间用于终止空字符。这可以通过将学生结构声明中的行char Age[2];
替换为来解决。char Age[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
. 因此,您实际上有一个无限循环,使您无法从主菜单退出程序。