【问题标题】:Buffer overflow or something else缓冲区溢出或其他
【发布时间】:2016-12-18 07:37:19
【问题描述】:

我正在创建一个关于座位预订的程序。我被要求对一些变量使用 unsigned short 和 unsigned int,这就是为什么它们被设置成这样。 我有一个工作正常的程序。但是当我在函数中传输所有内容时,一切似乎都正常,但在我的结构中奇怪的值开始被保存在所有地方.. 我只想保存文件的值(从第 2 行 -> 文件末尾)。 因为我有一个要初始化的结构,所以我首先要读取 txt 文件和座位数,我在函数(本地变量)和主体中声明了这个变量(乘客)2 次。 也许这会导致问题? 如果我不使用函数一切正常!

所以有问题的代码:

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

int i,j,numberofseats,temp;
char platenr[8],selection,buff[60];
char firstname[20];
char lastname[20];
char phone[11];
char *p;
typedef struct
    {
    char fullname[40];
    unsigned short phonenr[10];
    unsigned int seatnr;
    }PASSENGERS;

void readfile( void)
{
    FILE *businfo;
    businfo = fopen ("bus.txt","r");
    if (businfo == NULL)
        {
        printf("Error Opening File, check if file bus.txt is present");
        exit(1);}
    else
        {
        fscanf(businfo,"%s %d",platenr, &numberofseats);
        printf("Bus Licence plate Nr is: %s and number of seats is: %d", platenr, numberofseats);
        PASSENGERS passenger[numberofseats];
        for (j=0;j<numberofseats;j++)
            {passenger[j].seatnr=j+1;
            strcpy(passenger[j].fullname,"\0");
            }
        while (fgets(buff,sizeof(buff),businfo)!=0)
            {sscanf(buff, "%s %s %d %s", firstname, lastname, &temp,phone);
            strcpy(passenger[temp-1].fullname,firstname);
            strcat (passenger[temp-1].fullname, " ");
            strcat(passenger[temp-1].fullname,lastname);
            printf("%s",passenger[temp-1].fullname);
            i=0;
            for (p=phone;*p!='\0';p++)
                {
                (passenger[temp-1].phonenr[i])=*p -'0';
                i++;
                }
            }
           }
}

int main(void)
{
readfile();
PASSENGERS passenger[numberofseats];

【问题讨论】:

  • 我猜main() 不完整。另外,您知道函数readfile()main() 中的数组passenger 绝对没有关系,对吧?
  • 是的,我怀疑是这个问题。但是我怎样才能在函数内部初始化乘客数组,从txt文件中填写数据,然后在主体中保持相同的乘客数组?

标签: c function structure buffer buffer-overflow


【解决方案1】:

函数foo 中名为x 的变量与函数bar 中名为y 的变量无关。换句话说:main 中的passengerreadfile 中的passenger 是不同的变量。改变一个不会影响另一个。

你想要的可能更像这样:

int main(void)
{
    PASSENGERS passenger[numberofseats];
    readfile(passenger);
             ^^^^^^^^^
             Pass array as a pointer
    ....
}

void readfile(PASSENGERS* passenger)
{
    ....

    // REMOVE THIS: PASSENGERS passenger[numberofseats];


}

除此之外:

// Global variables gets zero initialized
int i,j,numberofseats,temp;
        ^^^^^^^^^^^^
        Becomes zero at start up

但你仍然在 main 中使用它:

PASSENGERS passenger[numberofseats];

这可能不是你真正想要的。

由于您尝试读取函数中的座位数,因此您确实希望使用动态内存分配。喜欢:

PASSENGERS* readfile()
{
     .....
     .....

     PASSENGERS* p = malloc(numberofseats * sizeof(PASSENGERS));

     .....
     .....
     return p;
}

int main(void)
{
    PASSENGERS* passenger = readfile();
     .....
     .....
     free(passenger);
     return 0;
}

如果您不想动态分配,则必须将numberofseats 的输入移动到main,以便在声明数组之前完成。

【讨论】:

  • 不,这是我的主要问题..我们不知道座位数,直到我们从 bus.txt 文件中读取信息,该文件位于 passeners[numberofseats] 声明之后..所以我根据您的建议修改了我的问题,但仍然有问题,可能是因为这个问题..
【解决方案2】:

问题是你在函数readfile()中声明了一个本地数组,一旦这个函数终止,它就丢失了。您需要能够将更改返回到main()。为此,您有一些选择。一是您可以在main() 中声明数组,并将您的函数更改为void readfile(PASSENGERS passenger[])。在这种情况下,您将执行以下操作:

int main()
{
PASSENGERS passenger[numberofseats];
readfile(passenger);
// more code

您将基本上传递一个指向存储在数组中的元素的内存位置的指针,本地到main(),该函数将填充数组,有效地返回更改。

另一种选择是在函数中动态分配一个数组(带有malloc() 系列),并使其返回一个类似PASSENGERS *readfile(void) 的指针。如果在编译时不知道席位的数量,此选项可能更合适,因此您需要在必要时动态增大或缩小数组。然而,这个选项让您有手动管理内存的负担,例如在完成后free()'ing 分配的内存。

既然你说你会从文件中读取numberofseats,那么后者会更好,所以你的代码看起来像这样:

PASSENGERS *readfile(void)
{ 
   FILE *businfo;
   PASSENGERS *passenger;
   businfo = fopen ("bus.txt","r");
   // do the checks, read the numberofseats
   passenger = malloc(numberofseats * sizeof *passenger);
   // read the values, fill the array
   fclose(businfo); // do not forget to close the file
   return passenger;
}

int main()
{
    PASSENGERS *passenger = readfile();
    // more code
    free(passenger);
    return 0;
}

【讨论】:

    【解决方案3】:

    好的,所以我所做的,在开始进行动态分配之前,在 main 开始时指定最大座位数,然后我完成了如下代码。我在第 43、109 行有 2 条警告消息,但似乎无法修复。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int i,j,numberofseats,temp;
    char platenr[8],selection;
    char firstname[20],lastname[20];
    char phone[11];
    char *p;
    typedef struct
        {
        char fullname[40];
        unsigned short phonenr[10];
        unsigned int seatnr;
        }PASSENGERS;
    
    void readfile(PASSENGERS passenger[])
    {   char buff[60];
        FILE *businfo;
        businfo = fopen ("bus.txt","r");
        if (businfo == NULL)
            {
            printf("Error Opening File, check if file bus.txt is present");
            exit(1);}
        else
            {
            fscanf(businfo,"%s %d",platenr, &numberofseats);
            printf("Bus Licence plate Nr is: %s, and Number of Seats is: %d.", platenr, numberofseats);
    
            for (j=0;j<numberofseats;j++)
                {passenger[j].seatnr=j+1;
                strcpy(passenger[j].fullname,"\0");
                }
            while (fgets(buff,sizeof(buff),businfo)!=0)
                {sscanf(buff, "%s %s %d %s", firstname, lastname, &temp,phone);
                strcpy(passenger[temp-1].fullname,firstname);
                strcat (passenger[temp-1].fullname, " ");
                strcat(passenger[temp-1].fullname,lastname);
                i=0;
                for (p=phone;*p!='\0';p++)
                    {
                    (passenger[temp-1].phonenr[i])=*p -'0';
                    i++;
                    }
                }
               }
    }
    
    void countfreeseats(PASSENGERS passenger[]){
        int freeseats = 0;
            for (j=0; j<numberofseats; j++)
                {
                strcmp(passenger[j].fullname,"\0")==0 ? freeseats = freeseats + 1 : freeseats ;}
                printf ("There are %d Free Seats in this Bus. \n", freeseats);
                printf("Seats that are Available are:\n");
    
            for (j=0; j<numberofseats; j++)
                {if (strcmp(passenger[j].fullname,"\0")==0)
                    printf ("%u\n", passenger[j].seatnr);
                }
            freeseats = 0;
            }
    
    void changeData(PASSENGERS *target){
        unsigned short tempdigit;
        printf("Enter Passenger's first name:");
        scanf("%s",firstname);
        printf("Enter Passenger's last name:");
        scanf("%s",lastname);
        strcpy(target->fullname,firstname);
        strcat (target->fullname, " ");
        strcat(target->fullname,lastname);
        printf("Enter Passenger's phone Nr:");
        scanf("%s",phone);
        i=0;
        for (p=phone;*p!='\0';p++)
            {
            (target->phonenr[i])=*p -'0';
            i++;
            }
    
    
        }
    
    void searchpassenger(PASSENGERS passenger[], char selection)
    {       char tempsel,tmpfirst[20],tmplast[20];
            unsigned short tempphone[10];
         if (selection == '1')
            {   printf("Enter Passenger's first name:");
                scanf("%s",tmpfirst);
                printf("Enter Passenger's last name:");
                scanf("%s",tmplast);
                strcat (tmpfirst, " ");
                strcat(tmpfirst,tmplast);
                for (j=0;j<numberofseats;j++)
                if (strcmp(passenger[j].fullname,tmpfirst)==0)
                    printf ("Passenger %s has Seat Nr #: %u\n",tmpfirst,passenger[j].seatnr);
            }
            else if (selection == '2')
            {   printf("Enter Passenger's Phone Nr:");
                scanf("%s",phone);
                i=0;
                for (p=phone;*p!='\0';p++)
                {
                (tempphone[i])=*p -'0';
                i++;
                }
                for (j=0;j<numberofseats;j++)
                {if (strcmp(tempphone,passenger[j].phonenr)==0)
                    printf("Passenger %s has Seat Nr %hd already Booked",passenger[j].fullname,passenger[j].seatnr);
                }
            }
            }
    
    
    
    void cancelSeat(PASSENGERS *target){
        strcpy(target->fullname,"\0");
        for (i=0;i<10;i++)
        target->phonenr[i]=0;
        printf("Seat Nr %d is now Free",temp);
    
        }
    
    void showList(PASSENGERS passenger[])
    {
     printf("The following Seats are Booked: \n Name, PhoneNr, SeatNr\n\n");                                    /*Emfanisi minimatos*/
            for (i=0; i<numberofseats; i++)
                if (strcmp(passenger[i].fullname,"\0")!=0)
                {
                    printf("%s, ",passenger[i].fullname);
                    for (j=0;j<10;j++)
                    {printf("%hu",passenger[i].phonenr[j]);}
    
                    printf(", %u\n",passenger[i].seatnr);
                }
    }
    
    
    void writeFile(PASSENGERS passenger[])
       {
        FILE * output;                                      /* Dilosi onomatos arxeiou */
        output = fopen("output.txt","w");    /*dimiourgia i eggrafi pano se iparxon arxeio me onoma output.txt,  mesw tis parametrou w*/
        fprintf(output,"%s %d \n",platenr,numberofseats);    /* mesw tis fprintf eksagogi pinakidas kai epikefalidas "Diagramma leoforeiou" sto arxeio output.txt. Allagi grammis opou xreiazetai*/
        for (i=0; i<numberofseats; i++)
            {if (strcmp(passenger[i].fullname,"\0")!=0)
            {
                fprintf(output,"%s ",passenger[i].fullname);
                fprintf(output,"%u ",passenger[i].seatnr);
                for (j=0;j<10;j++)
                fprintf(output,"%hu",passenger[i].phonenr[j]);
                fprintf(output,"%s","\n");
            }
            }
            fclose(output);                                     /* Kleisimo arxeiou*/
            printf("File Saved as Output.txt");
       }
    
    int main(void)
    {
    
    
    PASSENGERS passenger[53];
    readfile(passenger);
    
        do{
        printf("\n\nNeo Sistima Katagrafis Thesewn Leoforeiou\n");
        printf("Please make a selection:\n\n");
        printf("0. Exit\n");
        printf("1. Empty Seats \n");
        printf("2. Book Specific Seat \n");
        printf("3. Advanced Search of Booked Seats\n");
        printf("4. Cancel Seat Booking\n");
        printf("5. Show List of Booked Seats\n");
        scanf(" %c",&selection);
    
        if (selection=='1')
      countfreeseats(passenger);
    
        else if (selection=='2')
            {
            printf("Please give seat nr (between 1 and %d) that you want to book:\n", numberofseats);
            scanf("%d",&temp);
            if (temp >numberofseats || temp <= 0)
                {printf("Error: Seat nr should be between 1 and %d", numberofseats);}
             else if (strcmp(passenger[temp-1].fullname,"\0")!=0)
                printf("Error: Seat is already booked");
    
            else
            changeData(&passenger[temp-1]);
    
            }
    
     else if (selection=='3')
            {
            char tempsel;
            printf("Do you want to search with Name (1) or Phone Nr (2)?\n");
            scanf(" %c",&tempsel);
            searchpassenger(passenger,tempsel);
            }
    
    
    
    
    
        else if (selection=='4')
            {
            printf("Please give Seat Nr (between 1 and %d) that you want to Cancel Booking:\n", numberofseats);
            scanf("%d",&temp);
            if (temp >numberofseats || temp <= 0)
                {printf("Error: Seat nr should be between 1 and %d", numberofseats);}
             else if (strcmp(passenger[temp-1].fullname,"\0")==0)
                printf("Error: Seat is already free");
    
            else
            cancelSeat(&passenger[temp-1]);
    
            }
    
        else if (selection=='5')                                                            /*Menu 6 - Emfanisi listas kratimenon thesewn taksinomimenon kata ayksonta arithmo*/
            {
                showList(passenger);
    
            }
    
    
    
        } while (selection!='0');
        {
        writeFile(passenger);
        }
    
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-16
      • 1970-01-01
      • 2010-11-11
      • 1970-01-01
      • 2013-11-06
      • 2013-04-11
      • 2015-07-07
      • 2012-02-05
      相关资源
      最近更新 更多