缓冲区溢出或其他内容

时间:2016-12-18 07:37:20

标签: c function structure buffer buffer-overflow

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

所以有问题的代码:

#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];

3 个答案:

答案 0 :(得分:1)

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

void readfile(PASSENGERS passenger[])

您基本上会将指针传递给存储在数组中的元素的内存位置,本地为int main() { PASSENGERS passenger[numberofseats]; readfile(passenger); // more code ,函数将填充数组,从而有效地返回更改。

另一种选择是在函数中动态分配一个数组(带有main()族),并使它返回一个像malloc()这样的指针。如果在编译时不知道席位数,则此选项可能更合适,因此您需要在必要时动态增大或缩小阵列。但是,此选项使您无需手动管理内存,例如PASSENGERS *readfile(void)完成后分配的内存。

由于您说您将从文件中读取free(),后者将是更好的主意,因此您的代码将如下所示:

numberofseats

答案 1 :(得分:1)

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

你想要的可能更像是这样:

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,以便在声明数组之前完成。

答案 2 :(得分:0)

好的,所以我在开始进行动态分配之前所做的是指定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);
    }


    }