【问题标题】:Whats wrong when copying my nested struct?复制我的嵌套结构时出了什么问题?
【发布时间】:2018-10-12 15:31:18
【问题描述】:

我编写 C 代码是为了在编程和学习方面做得更好......并且有应该生成静态网页的程序。它还将项目保存为文本文件。我有单独的函数来制作对象(realloc 并放置一个新的结构......),并在这个场合将问题代码提取到一个短程序......它只是为了阅读“项目”。当我运行它时说:

分段错误(核心转储)

在 print_1_content 的中间

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

#define SELL_ITEM 1
#define PARAGRAPH_ITEM 2

struct SellItem {
  char  title[50];
  int nr_of_img;
  char ** image_files;//array of strings
};

struct ParagraphItem{
  char * text;
};

union ContentItem{//one of the following only
  struct SellItem s_item;
  struct ParagraphItem p_item;
};

struct Content{
  int type;//1=sellitem 2=paragraph
  union ContentItem c_item;
};

int open_items_file(struct Content **, int *, char *);
int free_1_item(struct Content *);
struct Content import_1_content(char *);
void increase(struct Content**, int *);
void print_1_content(struct Content *);
struct Content import_1_content(char *);
int free_1_item(struct Content *);

int main (void)
{
  struct Content * content;
  int content_count=0;

  open_items_file(&content, &content_count, "all_items.txt");   
  return 0;
}

int open_items_file(struct Content ** content, int * number_of_content, char * filename){
  printf("open_items_file %s\n", filename);

  FILE *fp = fopen(filename, "r");
  char * line = NULL;

  size_t len = 0;
  ssize_t read;
  int counter=0;

  if(fp==NULL){
    return 0;
  }
  //for each row
  while ((read = getline(&line, &len, fp)) != -1) {

  if((line[0]=='S' || line[0]=='P') && line[1]=='-'){
    if(line[3]==':'){
      if(line[2]=='I'){
        increase(content, number_of_content);
        *content[(*number_of_content)-1] = import_1_content(line);
      }
      else{
        //not sell/paragraph item
      }
    }//end if line[3]==':'
  }//end if line[0] =='S' eller 'P'

  counter++;
}
free(line);
fclose(fp);
return counter;
}

void increase(struct Content** content, int *nr_of_content){

  if((*nr_of_content)==0){
    *content = malloc(sizeof(struct Content));
  }
  else{
    *content = realloc(*content, (*nr_of_content+1) * sizeof(struct Content));
  }

  (*nr_of_content)++;
}

void print_1_content(struct Content * content){
  //Print info
}

struct Content import_1_content(char * text_line){
  struct Content temp_content_item;
  char * line_pointer = text_line;
  char c;
  line_pointer += 4;
  if(text_line[0]=='S'){

    temp_content_item.type = SELL_ITEM;
    temp_content_item.c_item.s_item.nr_of_img=0;
    int i=0;
    char * temp_text;

    while(*line_pointer != '|' && *line_pointer != '\n' && i < sizeof(temp_content_item.c_item.s_item.title)-1){
      temp_content_item.c_item.s_item.title[i] = *line_pointer;
      i++;//target index
      line_pointer++;
    }
  temp_content_item.c_item.s_item.title[i]='\0';

  i=0;

  //maybe images?
  short read_img_counter=0;
  if(*line_pointer == '|'){
    line_pointer++; //jump over '|'
    //img-file-name separ. by ';', row ends by '\n'
    while(*line_pointer != '\n'){//outer image filename -loop
      i=0;
      while(*line_pointer != ';' && *line_pointer != '\n'){//steps thr lett
        c = *line_pointer;      
        if(i==0){//first letter
          temp_text = malloc(2);
        }
        else if(i>0){
          temp_text = realloc(temp_text, i+2);//extra for '\0'
        }
        temp_text[i] = c;
        line_pointer++;
        i++;
      }
      if(*line_pointer==';'){//another image
        line_pointer++;//jump over ';'
      }
      else{
      }
      temp_text[i]='\0';
      //allocate
      if(read_img_counter==0){//create array
        temp_content_item.c_item.s_item.image_files = malloc(sizeof(char*));
      }
      else{//extend array
        temp_content_item.c_item.s_item.image_files = realloc(temp_content_item.c_item.s_item.image_files, sizeof(char*) * (read_img_counter+1));
      } 
      //allocate
      temp_content_item.c_item.s_item.image_files[read_img_counter] = calloc(i+1, 1);
      //copy
      strncpy(temp_content_item.c_item.s_item.image_files[read_img_counter], temp_text, strlen(temp_text));
      read_img_counter++;
      temp_content_item.c_item.s_item.nr_of_img = read_img_counter;
    }
  }
  else{
    printf("Item had no img-files\n");
  }
}
else{ // text_line[0]=='P'
  temp_content_item.type = PARAGRAPH_ITEM;
  temp_content_item.c_item.p_item.text = calloc(strlen(text_line)-4,1);


  int i=0;
  while(*line_pointer != '\0' && *line_pointer != '\n'){
    temp_content_item.c_item.p_item.text[i] = *line_pointer;
    i++;
    line_pointer++;
  }
}
print_1_content(&temp_content_item);
return temp_content_item;
}

int free_1_item(struct Content * item){
  if(item->type==SELL_ITEM){
    if(item->c_item.s_item.nr_of_img > 0){
    //Freeing img-names
    for(int i=0; i<item->c_item.s_item.nr_of_img; i++){
      free(item->c_item.s_item.image_files[i]);
    }
  }
return 1;
}
else if(item->type==PARAGRAPH_ITEM){
  //freeing p_item
  free(item->c_item.p_item.text);
  return 1;
}
else{
  printf("error: unknown item\n");
}
return 0;
}

要读取的文本文件(all_items.txt)是这样的,以换行符结尾,用于“sell-item”和“paragraph-item”两种内容类型:

S-I:Shirt of cotton|image1.jpg;image2.jpg;image3.jpg
P-I:A paragraph, as they are called.
S-I:Trousers, loose style|image4.jpg

【问题讨论】:

  • 你有什么问题?
  • 不相关,但您在哪里找到这些有趣的 TRUEFALSE 定义?只需使用10 (或包含stdbool.h 以拥有bool 类型和常量truefalse
  • 但是,确实,您应该描述实际问题。并将代码缩短到重现它所需的最低限度。这一切都在minimal reproducible example 中进行了解释。
  • 到底是哪一行崩溃了?
  • 一个主要问题是您动态分配对象,但print_1_ 按值获取对象。您应该改为通过指针传递它。您可以按值传递结构,但速度很慢,这也意味着它们包含的任何指针都将指向复制自结构的指针所指向的任何内容,因此它不是一个干净的副本。

标签: c struct malloc free unions


【解决方案1】:

所以你发现的问题出在这一行:

*content[(*number_of_content)-1] = temp_content_item2;

这是因为操作优先,因为*content[(*number_of_content)-1](*content)[(*number_of_content)-1]不一样,它实际上是在做*(content[(*number_of_content)-1])。因此,您的代码正在执行数组索引,然后取消引用指向内存中某个随机位置的引用。用这个替换那行,这将解决当前的问题。

(*content)[(*number_of_content)-1] = temp_content_item2;

【讨论】:

  • 谢谢你...你知道我为什么会在这里被否决吗?问候
  • @ValterEkholm 不知道(近 3 年前你确实问过这个问题),但通常是因为人们认为这个问题质量很差
猜你喜欢
  • 2013-06-28
  • 2021-06-23
  • 2018-09-11
  • 2011-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多