当我尝试使用 struct 运行程序时出现分段错误(核心转储) [英] I get segmentation fault (core dumped) when I tried to run program with struct

查看:30
本文介绍了当我尝试使用 struct 运行程序时出现分段错误(核心转储)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要读取一个文件并将文件中的数据存储到一个结构中.文件的第一行包含我必须动态分配的结构数组的大小.

I need to read a file and store the data from the file into a structure. The first line of the file contains the size of the array of structs that i have to dynamically allocate.

    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 来检查内存泄漏,这就是结果

I am to run my code perfectly in Windows but when I run in Unix environment it shows me segmentation fault (core dumped). I did use valgrind to check for the memory leak and that is the results

    ==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) 那个循环的部分,给出了问题.但我不知道如何解决它.

I need to read all the data from the file to the struct and print it out whenever user want the entry. I tried to debug part by part, and I found out it is the part while( fgets( line, sizeof( line ), file) != NULL) that loop, gives the problem. But I have no idea how to fix it.

我的struct.h如下:

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

推荐答案

我不太明白您要实现的所有目标,但这里有一些问题.

I don't quite understand all of what you are trying to achieve, but here are a few issues.

  1. 您可能不需要日月年变量.
  2. 这一行

  1. You probably don't need the day month year variables.
  2. This line

day = atoi(oken);

应该是

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

读取size

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

这读取一个整数但它不读取尾随的换行符

你需要把它改成这样

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

或使用 fgets.

由于尾​​随换行符,下次调用 gets 时,您将获得一个仅包含换行符的字符串.

Because of the trailing newline, the next time you call gets you obtain a string containing just the newline.

您的 strtok 调用和 NULL 检查不同步.第一个,对于 oken 是可以的.但是然后你做了一个 strtok 返回 coken 但对 oken 的空检查,最后一个 strtok 返回 yoken 和对 coken 的 NULL 检查.在所有 3 种情况下,对 strtok 的调用之后应该对返回值进行 NULL 检查(与 oken 的情况一样).

Your strtok calls and NULL checks are out of phase. The first one, for oken is OK. But then you do a strtok returning coken but a NULL check on oken and lastly a strtok returning yoken and a NULL check on coken. In all 3 cases, the call to strtok should be followed by a NULL check on the returned value (as is the case for oken).

我不明白 while (l 循环的目的(可能是因为上面描述的换行符处理不当?).您分配 5 个结构,从 structs.txt 中读取 4 个到 res2(元素 0 到 3)然后将 res2 的元素 1 到 4 复制到 res.这意味着 res2 的元素 0 不会被复制,元素 4 是全零会被复制.

I don't understand the purpose of the while (l < size) loop (maybe because of the mishandling of the newline as described above?). You allocate 5 structs, read 4 from structs.txt into res2 (elements 0 to 3) then you copy elements 1 to 4 of res2 into elements 0 to 3 of res. This means that element 0 of res2 doesn't get copied and element 4 which is all zeroes does get copied.

崩溃的原因是第 3 点和第 4 点的组合.

The cause of the crash is a combination of points 3 and 4.

我建议不要使用 atoi,因为它不进行错误检查.除非您确定字符串包含格式正确的整数,否则使用它是不安全的.如果你想让你的代码健壮,你需要添加更多的错误检查,例如,检查 malloccalloc 的返回值.

I would advise against using atoi as it does no error checking. It is unsafe to use unless you are certain that the string contains a well-formed integer. If you want your code to be robust, you need to add more error checking e.g., check the return values of malloc and calloc.

这篇关于当我尝试使用 struct 运行程序时出现分段错误(核心转储)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆