复制嵌套结构时有什么问题?

时间:2018-05-02 13:38:18

标签: c struct malloc free unions

我编写C代码以便在编程和学习方面做得更好......并且拥有应该生成静态网页的程序。它还将项目保存为文本文件。我有单独的函数来创建对象(realloc并放置一个新的结构......),并将问题代码提取到一个简短的程序中用于此场合...它只是用于阅读'项目& #39 ;.我跑的时候说:

  

分段错误(核心转储)

位于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)是这样的,以新行结尾,对于&#34; sell-item&#34;的两种内容类型。和&#34;段落项目&#34;:

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

1 个答案:

答案 0 :(得分: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;