Я получаю ошибку сегментации (ядро сброшено), когда я пытался запустить программу со структурой - PullRequest
0 голосов
/ 03 мая 2018

Мне нужно прочитать файл и сохранить данные из файла в структуре. Первая строка файла содержит размер массива структур, которые я должен динамически размещать.

    4
    12/04/2010
    Interview went well I think, though was told to wear shoes.
    18/04/2010
    Doc advised me to concentrate on something... I forget.
    03/05/2010
    Was asked today if I was an art exhibit.
    19/05/2010
    Apparently mudcakes not made of mud, or angry wasps.

Я должен отлично выполнить мой код в Windows, но когда я запускаю в среде Unix, это показывает мне ошибку сегментации (ядро сброшено). Я использовал valgrind для проверки утечки памяти, и это результаты

    ==4344== Invalid read of size 1
    ==4344==    at 0x407F842: ____strtol_l_internal (strtol_l.c:298)
    ==4344==    by 0x407F606: strtol (strtol.c:108)
    ==4344==    by 0x407C87E: atoi (atoi.c:27)
    ==4344==    by 0x8048837: main (in /home/admininistrator/ucp/p6/gg)
    ==4344==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
    ==4344== 
    ==4344== 
    ==4344== Process terminating with default action of signal 11 (SIGSEGV)
    ==4344==  Access not within mapped region at address 0x0
    ==4344==    at 0x407F842: ____strtol_l_internal (strtol_l.c:298)
    ==4344==    by 0x407F606: strtol (strtol.c:108)
    ==4344==    by 0x407C87E: atoi (atoi.c:27)
    ==4344==    by 0x8048837: main (in /home/admininistrator/ucp/p6/gg)
    ==4344==  If you believe this happened as a result of a stack
    ==4344==  overflow in your program's main thread (unlikely but
    ==4344==  possible), you can try to increase the size of the
    ==4344==  main thread stack using the --main-stacksize= flag.
    ==4344==  The main thread stack size used in this run was 8388608.
    ==4344== 
    ==4344== HEAP SUMMARY:
    ==4344==     in use at exit: 1,396 bytes in 3 blocks
    ==4344==   total heap usage: 3 allocs, 0 frees, 1,396 bytes allocated
    ==4344== 
    ==4344== LEAK SUMMARY:
    ==4344==    definitely lost: 0 bytes in 0 blocks
    ==4344==    indirectly lost: 0 bytes in 0 blocks
    ==4344==      possibly lost: 0 bytes in 0 blocks
    ==4344==    still reachable: 1,396 bytes in 3 blocks
    ==4344==         suppressed: 0 bytes in 0 blocks
    ==4344== Rerun with --leak-check=full to see details of leaked memory
    ==4344== 
    ==4344== For counts of detected and suppressed errors, rerun with: -v
    ==4344== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
    Segmentation fault (core dumped)

Вот мой код прилагается

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

int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        printf("You have enter less arguments.\n");
    }
    else if (argc > 2)
    {
        printf("You have enter too many arguments.");
    }
    else
    {
        FILE *file;
        Diary *res;
        Diary *res2;
        char line[102];
        int i, size, k, l, choice;
        int day, month, year;
        /* int d[10],m[10],y[10];*/
        char as[102];
        char* oken;
        char* yoken;
        char* coken;
        oken = NULL;
        yoken = NULL;
        coken = NULL;

        i = 0;

        file = fopen("struct.txt", "r");
        if (file == NULL)
        {
            perror("Error opening file\n.");
        }
        else
        {
            fscanf(file, "%d", &size);
            res = (Diary*) malloc(size * sizeof(Diary));
            res2 = (Diary*) calloc((5), sizeof(Diary));

            while (fgets(line, sizeof(line), file) != NULL)
            {
                oken = strtok(line, "/");
                if (oken != NULL)
                {
                    res2[i].day= atoi(oken);
                    coken = strtok(NULL, "/");
                    if (oken != NULL)
                    {
                        res2[i].month = atoi(coken);
                        yoken = strtok(NULL, "\n ");
                        if (coken != NULL)
                        {
                            /*printf("%s",yoken);*/
                            res2[i].year = atoi(yoken);

                            fgets(as, 102, file);
                            strncpy(res2[i].entry, as, 102);
                        }
                    }
                }
                i++;
            }
            k = 1;
            l = 0;

            while (l < size)
            {
                res[l].day = res2[k].day;
                res[l].month = res2[k].month;
                res[l].year = res2[k].year;
                strncpy(res[l].entry, res2[k].entry, 102);
                k++;
                l++;
            }

            choice = atoi(argv[1]);

            printf("%d-%02d-%02d:%s",res[choice].year, res[choice].month,res[choice].day,res[choice].entry);

            free(res2);
            free(res);
        }

        fclose(file);
    }

    return 0;
}

Мне нужно прочитать все данные из файла в структуру и распечатать их всякий раз, когда пользователь захочет записи. Я попытался отладить часть за частью, и я обнаружил, что это часть while( fgets( line, sizeof( line ), file) != NULL), которая создает проблему. Но я понятия не имею, как это исправить.

Мой struct.h указан ниже:

   typedef struct journal{
        int day;
        int month;
        int year;
        char entry[1024];
   } Diary;

1 Ответ

0 голосов
/ 03 мая 2018

Я не совсем понимаю все, чего вы пытаетесь достичь, но вот несколько вопросов.

  1. Возможно, вам не нужны переменные day month year.
  2. Эта строка

    day = atoi(oken);

    вероятно должно быть

    res2[i].day = atoi(oken);

  3. Проблема со строкой, которая читает size

    fscanf(file, "%d", &size)

    Здесь читается целое число , но не читается завершающий символ новой строки

    Вам нужно изменить это на что-то вроде

    fscanf(file, "%d\n", &size)

    или используйте fgets.

    Из-за завершающего перевода строки при следующем вызове gets вы получите строку, содержащую только перевод строки.

  4. Ваши strtok вызовы и проверки NULL не в фазе. Первый, для oken в порядке. Но затем вы делаете strtok, возвращающую coken, но NULL-проверку на oken и, наконец, strtok возвращающую yoken и NULL-проверку на coken. Во всех 3 случаях после вызова strtok должна следовать проверка NULL на возвращаемое значение (как в случае oken).

  5. Я не понимаю цели цикла while (l < size) (возможно, из-за неправильного обращения с новой строкой, как описано выше?). Вы выделяете 5 структур, читаете 4 из structs.txt в res2 (элементы с 0 по 3), затем копируете элементы с 1 по 4 из res2 в элементы с 0 по 3 из res. Это означает, что элемент 0 из res2 не копируется, а элемент 4 со всеми нулями копируется.

Причиной сбоя является сочетание пунктов 3 и 4.

Я бы не советовал использовать atoi, так как он не проверяет ошибки. Это небезопасно для использования, если вы не уверены, что строка содержит правильно сформированное целое число. Если вы хотите, чтобы ваш код был надежным, необходимо добавить дополнительную проверку ошибок, например, проверить возвращаемые значения malloc и calloc.

...