【问题标题】:Why am I getting a segmentation fault error when searching throught the file the second time?为什么在第二次搜索文件时出现分段错误错误?
【发布时间】:2017-06-16 04:32:50
【问题描述】:
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>


#define BUFSIZ 6

在这里,我在文件中搜索 3 个字符的代码,如果代码与令牌匹配,它应该输出您输入的代码。

void country_search(char code[6], FILE *dir, FILE *BAC_ptr){

    char *token_off;
    char *token;
    char buf[512];

    while (!feof(dir)){
        if (fgets(buf, 512 , dir)){
            token = strtok(buf,"1234567890");
            while (token != NULL){
                token = strtok(NULL,"1234567890");
                code = strtok(code,"\n");
                if ((strcmp(code,token)) == 0){
                printf("token: %s\n", token);
                }
            }
        }   
    }
}

int main(int argc, const char **argv) {

    char code[6];

    FILE *BAC_ptr;
    BAC_ptr = fopen("BinaryAllCountries.dat", "r");
    FILE *D_ptr;
    D_ptr = fopen("directory.dat", "r");

    fprintf(stdout, "Hello! welcome to the country database press type in: quit[enter] to quit at anytime\n");
    fprintf(stdout, "enter character code of the country you want:\n ");
    fgets(code, BUFSIZ, stdin);

当我使用 while 循环时,它会要求第一个输入然后接受它,运行 country_search() 方法然后返回,第二次它给我一个分段错误错误,我不知道为什么。

        while (strcmp(code, "quit\n") != 0) {
        fprintf(stdout, "enter another character code of the country you want: \n");
            country_search(code, D_ptr, BAC_ptr);
            fgets(code, BUFSIZ, stdin);
        }   
}

这是我的 directory.dat 文件

ABW3739AFG1511AGO43AIA3690ALB2635AND2654ANT4227ARE2547ARG5281ARM1532ASM4607ATA1336ATF1392ATG3721AUS4631AUT2675AZE1556BDI170BEL2717BEN62BFA149BGD1600BGR2775BHR1574BHS3759BIH2753BLR2695BLZ3797BMU3816BOL5302BRA5324BRB3778BRN1639BTN1620BVT1357BWA84CAF252CAN3837CCK4691CHE3597CHL5344CHN1684CIV355CMR193COD327COG307COK4715COL5367COM288CPV216CRI3887CUB3906CXR4658CYM3863CYP1703CZE2825DEU2956DJI376DMA3926DNK2846DOM3958DZA22ECU5389EGY396ERI447ESH1275ESP3519EST2867ETH470FIN2913FJI4740FLK5416FRA2934FRO2892FSM4857GAB489GBR3646GEO1745GHA529GIB2975GIN549GLP4044GMB509GNB574GNQ426GRC2996GRD4023GRL4004GTM4068GUF5442GUM4786GUY5459HKG1768HMD1433HND4109HRV2796HTI4087HUN3058IDN1813IND1790IOT122IRL3099IRN1832IRQ1851ISL3078ISR1871ITA3117JAM4130JOR1912JPN1892KAZ1936KEN592KGZ1980KHM1662KIR4806KNA4328KOR2356KWT1956LAO1998LBN2019LBR632LBY668LCA4352LIE3162LKA2380LSO613LTU3185LUX3208LVA3137MAC2037MAR818MCO3288MDA3270MDG691MDV2081MEX4174MHL4834MKD3231MLI731MLT3249MMR2125MNG2103MNP5001MOZ843MRT755MSR4194MTQ4153MUS776MWI712MYS2060MYT796NAM864NCL4900NER884NFK4965NGA907NIC4250NIU4940NLD3314NOR3334NPL2145NRU4874NZL4925OMN2189PAK2213PAN4270PCN5065PER5498PHL2262PLW5018PNG5048POL3355PRI4295PRK2171PRT3377PRY5481PSE2236PYF4769QAT2280REU927ROM3399RUS3433RWA947SAU2307SDN1142SEN1025SGP2330SGS1485SHN970SJM3552SLB5111SLE1073SLV3983SMR3455SOM1095SPM4388STP1004SUR5519SVK3477SVN3499SWE3572SWZ1165SYC1047SYR2400TCA4500TCD270TGO1206THA2468TJK2445TKL5129TKM2513TMP1724TON5146TTO4464TUN1227TUR2487TUV5164TWN2421TZA1188UGA1248UKR3617UMI5208URY5540USA4529UZB2572VAT3036VCT4433VEN5564VGB4555VIR4581VNM2594VUT5228WLF5257WSM5083YEM2614YUG3671ZAF1122ZMB1295

【问题讨论】:

  • 第二次你已经在那个文件的末尾了。
  • 请注意,一旦文件被读取,您就不要rewind(尽管我认为程序不会因此而崩溃)
  • code 只有 5 个字符的空间,但 "quit\n" 需要 6 个(计算 '\0' 和结尾)。
  • 如果缓冲区的实际大小只有5,为什么BUFSIZ 6?!

标签: c file segmentation-fault


【解决方案1】:

程序在以下行崩溃(valgrind 马上告诉我):

if ((strcmp(code,token)) == 0){

为什么?因为你测试NULL太早了

    while (token != NULL){
        token = strtok(NULL,"1234567890"); <- right here TOKEN can be set to NULL!
        /* code = strtok(code,"\n"); MUST be moved elsewhere*/
         if ((strcmp(code,token)) == 0){
           printf("token: %s\n", token);
         }

要解决,只需在适当的位置插入NULL 检查:

while (token != NULL) {
    token = strtok(NULL,"1234567890");
    if (token)
    {
        if (strcmp(code,token) == 0){ /* no need for extra parens here */
          printf("token: %s\n", token);
        }
    }
}

补充几点:

  1. BAC_PTR 未使用。
  2. 将删除\n 的行从code 移到安全的地方。最好在循环之外......但更好,
  3. 输入空行也会导致崩溃。所以输入后直接去掉\n,然后测试空行。
  4. 你的 512 缓冲区不好。对于整个 directory.dat 文件来说,它太小了,其中一个 3 字母代码会被切成两半。

【讨论】:

  • BAC_ptr 将被使用,只是还没有到达那里,是的,我现在只是将 512 作为随机数,这将改变这一点,谢谢。我将使用 valgrind 我会查一下谢谢。
  • @jhowe:这样做不会对您造成伤害,但我已经学会了如何解读 valgrind 有时含糊的信息。找到一个好的调试器——gdb 听起来对你来说很好——这样你就可以一次单步执行你的代码,并在执行此操作时查看变量值的变化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2018-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多