【问题标题】:segmentation fault in c Debian but not in windows [closed]c Debian中的分段错误但在Windows中没有[关闭]
【发布时间】:2021-08-03 06:27:28
【问题描述】:

我对两者都使用了相同的代码,但我在 Debian 中遇到了分段错误。为什么会出现这个错误?

注意:我知道代码没有意义,这是学校的作业。下面添加了错误图像。我调查了类似的主题,但没有找到错误解决方案。

Error image in Debian

Works fine for windows

代码如下:

#include <stdio.h>
#include <string.h>

struct record {
    char name[64]; //utf16
    char surname[32]; //utf8
    char gender[1];
    char email[32];
    char phone_number[16];
    char address[32];
    char level_of_education[8];
    unsigned int income_level; // given little-endian
    unsigned int expenditure; // given big-endian
    char currency_unit[16];
    char currentMood[32];
    float height;
    unsigned int weight;

};

struct tag {
    char name[5];
    char surname[8];
    char gender[7];
    char email[10];
    char phone_number[13];
    char address[8];
    char level_of_education[19];
    char income_level[13];
    char expenditure[12];
    char currency_unit[14];
    char currentMood[12];
    char height[7];
    char weight[7];

};

/*
 * Converts big endian to little or little endian to big endian
 */
unsigned int endian_swap(unsigned int x)
{
    x = (x>>24) | 
        ((x<<8) & 0x00FF0000) |
        ((x>>8) & 0x0000FF00) |
        (x<<24);
        
    return x;
}

/*
 * Find uncorrect tag headers and fixed 
 */
struct tag rearrange_tag_names(struct tag t){
    struct tag *tagPtr;
    tagPtr = &t;
    // Check name header
    if(strcmp(t.name,"name") != 0) {
        strncpy(tagPtr->name,"name",5);
    }
     // Check surname header
    if(strcmp(t.surname,"surname") != 0) {
        strncpy(tagPtr->surname,"surname",8);
        
    }
     // Check gender header
    if(strcmp(t.gender,"gender") != 0) {
        strncpy(tagPtr->gender,"gender",7);
    }
    // Check email header
    if(strcmp(t.email,"email") != 0) {
        strncpy(tagPtr->email,"email",10);
    }
    // Check phone_number header
    if(strcmp(t.phone_number,"phone_number") != 0) {
        strncpy(tagPtr->phone_number,"phone_number",13);        
    }
    // Check address header
    if(strcmp(t.address,"address") != 0) {
        strncpy(tagPtr->address,"address",8);
    }
    // Check level_of_education header
    if(strcmp(t.level_of_education,"level_of_education") != 0) {
        strncpy(tagPtr->level_of_education,"level_of_education",20);
    }
    // Check income_level header
    if(strcmp(t.income_level,"income_level") != 0) {
        strncpy(tagPtr->income_level,"income_level",14);        
    }
    // Check expenditure header
    if(strcmp(t.expenditure,"expenditure") != 0) {
        strncpy(tagPtr->expenditure,"expenditure",12);
    }
    // Check currency_unit header
    if(strcmp(t.currency_unit,"currency_unit") != 0) {
        strncpy(tagPtr->currency_unit,"currency_unit",14);
    }
    // Check currentMood header
    if(strcmp(t.currentMood,"currentMood") != 0) {
        strncpy(tagPtr->currentMood,"currentMood",12);
    }
    // Check height header
    if(strcmp(t.height,"height") != 0) {
        strncpy(tagPtr->height,"height",7);
    }
    // Check weight header
    if(strcmp(t.weight,"weight") != 0) {
        strncpy(tagPtr->weight,"weight",7);
    }


    // print to test
    //printf("%s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s \t %s",t.name,t.surname,t.gender,t.email,t.phone_number,t.address,t.level_of_education,t.income_level,t.expenditure,t.currency_unit,t.currentMood,t.height,t.weight);
    return t;
}

/*
 * Creates XML from given records
 */
void createXML(struct record* arr,struct tag tag,char *xml_name)
{
    // Create file pointer
    FILE  *fxml;
    //Check if error is occured
    if ((fxml = fopen(xml_name,"wt")) == NULL) {    
        printf("%s","Some error is occured.");
                                          
    }


    fprintf (fxml,"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
    fprintf(fxml,"<records>\n");
    int i;

    // Print tag to test
    //printf("%s",tag.email);
    //printf("%s",tag.level_of_education);
    // printf("%s",tag.level_of_education);
    // printf("%s",tag.income_level);
    // printf("%s",tag.expenditure);
    // printf("%s",tag.height);
    // printf("%s",tag.weight);
    
    // Crate xml rows
    for (i = 1; i < 51; i++) {
        
        fprintf(fxml,"   <row id='%d'>\n",i);
        fprintf(fxml,"       <%s>%s</%s>\n",tag.name,arr[i].name,tag.name);
        fprintf(fxml,"       <%s>%s</%s>\n",tag.surname,arr[i].surname,tag.surname);
        fprintf(fxml,"       <%s>%s</%s>\n",tag.gender,arr[i].gender,tag.gender);
        fprintf(fxml,"       <%s>%s</%s>\n",tag.email,arr[i].email,tag.email);
        fprintf(fxml,"       <%s>%s</%s>\n",tag.phone_number,arr[i].phone_number,tag.phone_number);
        fprintf(fxml,"       <%s>%s</%s>\n",tag.address,arr[i].address,tag.address);
        fprintf(fxml,"       <%s>%s</%s>\n",tag.level_of_education,arr[i].level_of_education,tag.level_of_education);
        fprintf(fxml,"       <%s>%d</%s>\n",tag.income_level,arr[i].income_level,tag.income_level);
        fprintf(fxml,"       <%s>%d</%s>\n",tag.expenditure,arr[i].expenditure,tag.expenditure);
        fprintf(fxml,"       <%s>%s</%s>\n",tag.currency_unit,arr[i].currency_unit,tag.currency_unit);
        fprintf(fxml,"       <%s>%s</%s>\n",tag.currentMood,arr[i].currentMood,tag.currentMood);
        fprintf(fxml,"       <%s>%.2f</%s>\n",tag.height,arr[i].height,tag.height);
        fprintf(fxml,"       <%s>%d</%s>\n",tag.weight,arr[i].weight,tag.weight);
        fprintf(fxml,"   </row>\n");
        
    }
    fprintf(fxml,"</records>\n");

    fclose(fxml); //Close file
}


/*
 * Converts bin file to XML
 */
int Bin2XML(char* rafname,char* xml_name)      
{
    // Create necessary variables
    FILE *fraf;
    struct record rec;
    struct tag tag;
    
    struct record arr_rec[50];
    int number_of_record = 51;


    // Encode file in utf-8 format
    if ((fraf = fopen(rafname,"rb, ccs=UTF-8")) == NULL)
        return 0;                                   // failure

    

    fread(&arr_rec, sizeof(struct record), number_of_record, fraf);

    // Read first line into tag and 
    // make necessary convertion and arrangement
    strcpy(tag.name,arr_rec[0].name);
    strcpy(tag.surname,arr_rec[0].surname);
    strcpy(tag.email,arr_rec[0].email);
    strcpy(tag.phone_number,arr_rec[0].phone_number);
    strcpy(tag.address,arr_rec[0].address);
    strcpy(tag.level_of_education,arr_rec[0].level_of_education);
    // convert int income level to string format
    char converted_income_level[10];
    sprintf(converted_income_level,"%d",arr_rec[0].income_level);
    strcpy(tag.income_level,converted_income_level);
    // convert int expenditure  to string format
    char converted_expenditure[10];
    sprintf(converted_expenditure,"%d",arr_rec[0].expenditure);
    strcpy(tag.expenditure,converted_expenditure);
    strcpy(tag.currency_unit,arr_rec[0].currency_unit);
    strcpy(tag.currentMood,arr_rec[0].currentMood);
    // convert float height  to string format
    char buf[10];
    snprintf(buf,5,"%s",arr_rec[0].height);
    
    strcpy(tag.height,buf);
    // convert unsigned weight to string format
    char converted_weight[10];
    sprintf(converted_weight,"%d",arr_rec[0].weight);
    strcpy(tag.weight,converted_weight);
    
    
    tag = rearrange_tag_names(tag);
   
    // Rearrange formats
    int i;
    for(i=1;i<number_of_record;i++){
        arr_rec[i].expenditure = endian_swap(arr_rec[i].expenditure); // Convert big endian to little endian
        // Income level is already little endian but if it was not little endian we can read as little endian
        // with endian_swap function.
        //arr_rec[i].income_level =endian_swap(arr_rec[i].income_level);    
        
        }

    // Create an XML file with readed records
    // First record readed into tag,so we can decrease number of record by one
    createXML(arr_rec,tag,xml_name);

    // close file
    fclose(fraf);
    
    return 1;                                       // success
}



int main(void)
{
  
    if( Bin2XML("records.dat","test.xml") == 1 ){
        printf("Bin file is readed and XML file is created successfully.");
    } else{
        printf("(!) An error occured please check your input file name. (!)");
    }

    return 0;
}

有人可以帮我吗?

【问题讨论】:

  • 像 gdb 这样的调试器可以轻松地向您准确显示段错误发生的位置,而无需我们通过几百行代码来尝试找到问题。
  • 我去看看
  • 我对两者都使用了相同的代码,但我在 Debian 中遇到了分段错误。为什么会出现此错误? 这是调用 undefined behavior 的代码的典型行为 - 它有时或在某处工作,但在其他条件下或在另一个系统上运行时会失败。我看到不少strcpy() 调用可能导致缓冲区溢出,还有不少strncpy() calls that could result in a non-terminated string
  • 我会尝试摆脱这些 strcpy() 和 strncpy()。
  • 你有大量的代码复制。您还有 UB:strncpy(tagPtr-&gt;income_level,"income_level",14) --> strncpy(tagPtr-&gt;income_level,"income_level",13)(因为:char income_level[13];)。您的记录字段不确定是否需要 EOS 的空间(例如)char hello[5] = "hello"; 没有空间用于 '\0'char hello[6] = "hello"; 需要。但是,由于 %s 格式,您的打印代码 假定 为 EOS 空间。您的文件/磁盘数据(来自fread)是否为 all 字段提供 EOS 空间?

标签: c segmentation-fault debian


【解决方案1】:

线

snprintf(buf, 5, "%s", arr_rec[0].height);

错误:arr_rec[0].height 是一个浮点数,而格式 "%s" 指定一个字符串。

这意味着 snprintf() 可以随意访问内存。这会导致未定义的行为,根据地址是什么,这可能是 Windows 下的分段错误或访问冲突。

顺便说一句,我刚刚编译了你的代码,编译器(MSVC)立即给出了错误:

warning C4477: 'snprintf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'double'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    相关资源
    最近更新 更多