为什么我的功能会使程序崩溃?

时间:2013-12-12 15:10:10

标签: c

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

struct packets
{
int source, destination, type, port;
char data[50];
};

int addpacket(int *, struct packets *);
void listpackets(int , struct packets *); 
void save(int, struct packets *);

int main()
{

struct packets *info;
char choice;
int records = 0;

info = malloc(sizeof(struct packets));

 do
 {
     puts("\n1. Add Packets\n");                //Menu with list of options.
     puts("\n2. List all saved packets\n");
     puts("\n3. Save packets\n");
     puts("\n4. Clear all packet information\n");
     puts("\nx. Exit the programme\n");
     printf("\nPlease select your option: \n");
     scanf("%c", &choice);     //Reading the menu option entered.

       if(choice == '\n')      //if the choice is the new line character read again.
            scanf("%c", &choice);

    switch (choice)
        {
            case '1': system("cls"); //Clears the screen
                      puts("\nYou have selected to Add packet information, follow on-screen instructions\n"); records = addpacket(&records, info); //calls function "addpacket" and sents a copy of records and pointer to struct info.
                      break;
            case '2': system("cls"); //clears the screen
                      puts("\nAll packet information will now be displayed on the screen\n"); listpackets(records, info);
                      break;
            case '3': system("cls"); //clears the screen
                      puts("\nAll packet information will now be saved\n"); save(records, info);
                      break;
            case '4': system("cls"); //clears the screen
                      puts("\nAll packet information will now be deleted\n");
                      break;
            case 'x': puts("\nThe proframme will now close, Goodbye!\n"); //closes the programme.
                      break;
            default : puts("\nIncorrect option, please select from menu\n"); //used if none of the menu options have been selected.
                      break;
        }
 }while (choice != 'x');    //The programme will run until the "x" option is entered at the menu.
return 0;
}

int addpacket(int *recCount, struct packets *info)
{
int validation = 0;
int stringlength = 0;
int i = 0;
char datatest[50];

do{
        printf("\nPlease enter the source address: \n");
        if (scanf("%i", &info[*recCount].source) == 1)
        {
            validation = 1;
        }
        else{
                validation = 0;
                getchar();
                puts("\nThis is not a valid source address!\n");
            }
    }while (validation != 1);

    printf("\nPlease enter destination address: \n");
    scanf("%i", &info[*recCount].destination); //pointer to the destination address.

printf("\nPlease enter type: \n");
scanf("%i", &info[*recCount].type); // pointer to the address of the type.
printf("\nPlease enter the port: \n");
scanf("%i", &info[*recCount].port); //pointer to the port address.
printf("\nPlease enter data: \n");
scanf("%s", info[*recCount].data); //pointer to the data address.

*recCount ++; //adding one to record count

return *recCount; // returning the record count which will the be copied into records in main.
}

void listpackets(int records, struct packets *info)
{
int i;
for (i=0; i<records; i++){
    printf("\nSource address: %i\n", info[i].source); //Displays the source address.
    printf("\nDestination address: %i\n", info[i].destination);  //Displays the destination address.
    printf("\nType: %i\n", info[i].type); //Displays the type.
    printf("\nPort: %i\n", info[i].port); //displays the port.
    printf("\nData: %s\n", info[i].data); //displays the data information.
}
}

void save(int records, struct packets *info)
{
FILE *savedfile;
char filename[30] = { '\0'}; //this is where the file name will be stored.
int i;

printf("\nPlease enter a filename: \n");
scanf("%s", filename);

if ((savedfile = fopen(filename, "w")) == NULL)
{
    printf("\n%s could not be opened\n", filename);
    exit(1);
}
else
{
    for (i=0; i<records; i++)
        fprintf(savedfile, "%i %i %i %i %s", info[i].source, info[i].destination, info[i].type, info[i].port, info[i].data);
}
fclose(savedfile);
}

我调用时,我的save和listpacket函数崩溃了。这工作得早,直到我将malloc引入我的程序并进行一些基本的输入验证。我认为这可能是指针的问题。我的程序编译没有错误/警告所以我坚持问题可能是什么。随意尝试编译程序,看看我的意思。任何帮助都会非常感激,因为我正在努力解决这个问题。

1 个答案:

答案 0 :(得分:2)

您正在使用malloc()为单个struct packets分配空间。您稍后会将info指针视为records这样的结构数组......您将超出已分配空间的边界。

有关一种潜在方式的详细信息(将自动增长您的阵列):

// change the signature of addpacket():
int addpacket(int *, struct packets **);

...

// change how add packet gets called:
    records = addpacket(&records, &info);

// change addpacket():
int addpacket(int *recCount, struct packets **callerinfo)
{
    ...
    // grow the buffer by one record
    *callerinfo = realloc(*callerinfo, (*recCount + 1) * sizeof (**callerinfo));
    struct packets *info = *callerinfo; // to avoid changing other code
    ... no other changes, just the rest of your routine
}

那将会接近,而不是完全解决它。

完整的计划,为我工作:

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

struct packets
{
int source, destination, type, port;
char data[50];
};

int addpacket(int *, struct packets **);
void listpackets(int , struct packets *); 
void save(int, struct packets *);

int main()
{
    struct packets *info;
    char choice;
    int records = 0;

    info = malloc(sizeof(struct packets));

     do
     {
         puts("\n1. Add Packets\n");                //Menu with list of options.
         puts("\n2. List all saved packets\n");
         puts("\n3. Save packets\n");
         puts("\n4. Clear all packet information\n");
         puts("\nx. Exit the programme\n");
         printf("\nPlease select your option: \n");
         scanf("%c", &choice);     //Reading the menu option entered.

         if(choice == '\n')      //if the choice is the new line character read again.
            scanf("%c", &choice);

          switch (choice)
          {
            case '1': system("cls"); //Clears the screen
                      puts("\nYou have selected to Add packet information, follow on-screen instructions\n"); records = addpacket(&records, &info); //calls function "addpacket" and sents a copy of records and pointer to struct info.
                      break;
            case '2': system("cls"); //clears the screen
                      puts("\nAll packet information will now be displayed on the screen\n"); listpackets(records, info);
                      break;
            case '3': system("cls"); //clears the screen
                      puts("\nAll packet information will now be saved\n"); save(records, info);
                      break;
            case '4': system("cls"); //clears the screen
                      puts("\nAll packet information will now be deleted\n");
                      break;
            case 'x': puts("\nThe proframme will now close, Goodbye!\n"); //closes the programme.
                      break;
            default : puts("\nIncorrect option, please select from menu\n"); //used if none of the menu options have been selected.
                      break;
          }
      }while (choice != 'x');    //The programme will run until the "x" option is entered at the menu.
    return 0;
}

int addpacket(int *recCount, struct packets **callerinfo)
{
    int validation = 0;
    int stringlength = 0;
    int i = 0;
    char datatest[50];

    *callerinfo = realloc(*callerinfo, (*recCount + 1) * sizeof (**callerinfo));
    struct packets *info = *callerinfo; // to avoid changing other code

    do{
        printf("\nPlease enter the source address: \n");
        if (scanf("%i", &info[*recCount].source) == 1)
        {
            validation = 1;
        }
        else{
                validation = 0;
                getchar();
                puts("\nThis is not a valid source address!\n");
            }
    }while (validation != 1);

    printf("\nPlease enter destination address: \n");
    scanf("%i", &info[*recCount].destination); //pointer to the destination address.

    printf("\nPlease enter type: \n");
    scanf("%i", &info[*recCount].type); // pointer to the address of the type.
    printf("\nPlease enter the port: \n");
    scanf("%i", &info[*recCount].port); //pointer to the port address.
    printf("\nPlease enter data: \n");
    scanf("%s", info[*recCount].data); //pointer to the data address.

    ++(*recCount); //adding one to record count

    return *recCount; // returning the record count which will the be copied into records in main.
}

void listpackets(int records, struct packets *info)
{
    int i;
    for (i=0; i<records; i++){
        printf("\nSource address: %i\n", info[i].source); //Displays the source address.
        printf("\nDestination address: %i\n", info[i].destination);  //Displays the destination address.
        printf("\nType: %i\n", info[i].type); //Displays the type.
        printf("\nPort: %i\n", info[i].port); //displays the port.
        printf("\nData: %s\n", info[i].data); //displays the data information.
    }
}

void save(int records, struct packets *info)
{
    FILE *savedfile;
    char filename[30] = { '\0'}; //this is where the file name will be stored.
    int i;

    printf("\nPlease enter a filename: \n");
    scanf("%s", filename);

    if ((savedfile = fopen(filename, "w")) == NULL)
    {
        printf("\n%s could not be opened\n", filename);
        exit(1);
    }
    else
    {
        for (i=0; i<records; i++)
            fprintf(savedfile, "%i %i %i %i %s\n", info[i].source, info[i].destination, info[i].type, info[i].port, info[i].data);
    }
    fclose(savedfile);
}