char *在嵌套结构中产生意外的结果

问题描述:

我正在开发一些从xml文档检索某些值并使用嵌套结构指针来帮助我管理数据的过程。char *在嵌套结构中产生意外的结果

我遇到我的结构之一内的字符串值意外行为:

这是程序:

void parseInlineElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){ 

do { 
    if (xmlStrcmp (node->name, XMLSTR("AdSystem")) == 0){ 

     xmlFile->Ads->data->Inline->AdSystem = (char *)node->children->content; // does not work - displays �9; 
     xmlFile->Ads->data->Inline->AdSystem = "Works"; // works 
     printf ((char *)node->children->content); // works 
    } 
    else if (xmlStrcmp (node->name, XMLSTR("Creatives")) == 0){ 
     parseCreatives (doc, node->children, xmlFile); 
    } 

    } while((node = node->next)); 

} 

这是我有问题行:

xmlFile->Ads->data->Inline->AdSystem = (char *)node->children->content; 

当我在我的程序中测试结果时,该值看起来像没有指向内存中正确的位置,因为它会产生垃圾,即:“ 9”,其中期望值为“广告系统”

如果我存储的测试值“作品” - 这里没有任何问题

如果我连打印节点值,这也适用:“广告系统”

在此先感谢

- 头文件

/* 
* daastXML.h 
* 
* Created on: Nov 27, 2015 
*  Author: hearme 
*/ 

#ifndef DAASTXML_H_ 
#define DAASTXML_H_ 

#define VECTOR_INITIAL_CAPACITY 100 

// Define a vector type 
typedef struct { 
    int size;    // slots used so far 
    int capacity;   // total available slots 
    struct daastAd *data;  // array of ads we're storing 

    char * testData; 
} VectorAds; 

typedef struct { 
    int size;    // slots used so far 
    int capacity;   // total available slots 
    struct daastCreative *data;  // array of ads we're storing 
} VectorCreatives; 

typedef struct { 
    int size; 
    int capacity; 
    struct daastMediaFile *data; 
} VectorMediaFiles; 


struct daastInline { 

    // Required elements 
    char *AdTitle; 
    char *Impression; 
    VectorCreatives *Creatives; 
    char *Category; 

    // Optional elements 
    char *AdSystem; 
    char *Description; 
    char *Advertiser; 
    char *Expires; 

    // Multiple survey urls 
    // Multiple error urls 

    char *Pricing; 

    // Extensions - for custom xml extensions 

}; 

struct daastXML { 
    char *version; 
    VectorAds *Ads; 
}; 

struct daastAd { 
    char *id; 
    char *sequence; 
    struct daastInline *Inline; 
}; 

struct daastMediaFile { 
    char *id; 
    char *delivery; 
    char *type; 
    char *url; 
    char *bitRate; 
}; 

struct daastLinear { 
    char *duration; 
    VectorMediaFiles MediaFiles; 

}; 

struct daastCreative { 
    struct daastLinear linear; 
}; 



// Main handler 
void processDaast (char * filePath, struct daastXML *xmlFile); 



// Methods used to manage Ads collection 
void vectorAds_init(VectorAds *vector); 
void vectorAds_append(VectorAds *vector, struct daastAd value); 
struct daastAd vectorAds_get(VectorAds *vector, int index); 
void vectorAds_set(VectorAds *vector, int index, struct daastAd value); 
void vectorAds_double_capacity_if_full(VectorAds *vector); 
void vectorAds_free(VectorAds *vector); 

// Methods used to manage Creatives collection 
void vectorCreatives_init(VectorCreatives *vector); 
void vectorCreatives_append(VectorCreatives *vector, struct daastCreative value); 
struct daastCreative VectorCreatives_get(VectorCreatives *vector, int index); 
void vectorCreatives_set(VectorCreatives *vector, int index, struct daastCreative value); 
void vectorCreatives_double_capacity_if_full(VectorCreatives *vector); 
void vectorCreatives_free(VectorCreatives *vector); 

// Methods used to manage Creatives collection 
void vectorMediaFiles_init(VectorMediaFiles *vector); 
void vectorMediaFiles_append(VectorMediaFiles *vector, struct daastMediaFile value); 
struct daastMediaFile vectorMediaFiles_get(VectorMediaFiles *vector, int index); 
void vectorMediaFiles_set(VectorMediaFiles *vector, int index, struct daastMediaFile value); 
void vectorMediaFiles_double_capacity_if_full(VectorMediaFiles *vector); 
void vectorMediaFiles_free(VectorMediaFiles *vector); 


#endif /* DAASTXML_H_ */ 

C语言文件 /* * daastXML.c * *创建于:2015年11月27日 *作者:hearme */

#ifndef DAASTXML_C_ 
#define DAASTXML_C_ 

#define XMLSTR(str) ((xmlChar *)(str)) 

#include "daastXML.h" 
#include <libxml/xmlmemory.h> 
#include <libxml/parser.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

void parseAds(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile); 
void parseInline(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile); 
void parseInlineElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile); 
void parseCreatives(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile); 
void parseCreativesElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile); 
void parseCreativeElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile); 
void parseLinear (xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile); 
void parseMediaFiles (xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile); 


void processDaast (char * filePath, struct daastXML *xmlFile){ 

    xmlDocPtr doc; 
    xmlNodePtr node; 

    doc = xmlParseFile(filePath); 
    node = xmlDocGetRootElement(doc); 


    if (xmlStrcmp (node->name, XMLSTR("DAAST")) == 0){ 

     xmlFile->version = (char *)xmlGetProp(node, XMLSTR("version")); 
     parseAds(doc, node->children, xmlFile); 

    } 

    xmlFreeDoc(doc); 

} 

void parseAds(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){ 

    // Allocate new instance of the VectorAds and assign it to the xmlFile, set default data 
    VectorAds *Ads; 
    Ads = (VectorAds *) malloc (sizeof(VectorAds)); 

    Ads->testData = "testData"; 
    xmlFile->Ads = Ads; 

    // Initialise the vector 
    vectorAds_init(xmlFile->Ads); 



    do { 
     if (node == NULL) break; 
     if (xmlIsBlankNode(node)) continue; 

    if (xmlStrcmp (node->name, XMLSTR("Ad")) == 0) { 

     // Set up new advert 
     struct daastAd *newAd; 
     newAd = (struct daastAd *) malloc (sizeof(struct daastAd)); 

     // Set add properties 
     newAd->id = (char *)xmlGetProp(node, XMLSTR("id")); 
     newAd->sequence = (char *)xmlGetProp(node, XMLSTR("sequence")); 

     vectorAds_append(xmlFile->Ads, *newAd); 

     // At this point we need to get the inline (or wrapper) info *** WRAPPER NOT INTEGRATED *** 
     parseInline (doc, node->children, xmlFile); 

    } 
} while ((node = node->next)); 


} 

void parseInline (xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){ 


// Set up Inline Property Here 
struct daastInline *Inline; 
Inline = (struct daastInline *) malloc (sizeof(struct daastInline)); 

// Assing Inline Property 
xmlFile->Ads->data->Inline = Inline; 

do { 
    if (node->type == XML_ELEMENT_NODE){ 
     if (xmlStrcmp (node->name, XMLSTR("InLine")) == 0){ 

      // Various parses at this level 
      parseInlineElements(doc, node->children, xmlFile); 
      //xmlFile->Ads->data->Inline->AdSystem = "AdSystem"; 

      // Should this be here? 
      //parseCreatives (doc, node->children, xmlFile); 

      break; 
     } 
    } 
} while((node = node->next)); 
} 

void parseInlineElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){ 

// loop through Inline child elements, and pick out the values 
//* 
do { 
    if (xmlStrcmp (node->name, XMLSTR("AdSystem")) == 0){ 
     char *nodeValue = (char *) node->children->content; 
     xmlFile->Ads->data->Inline->AdSystem = malloc (sizeof(char)); 
     strcpy (xmlFile->Ads->data->Inline->AdSystem, nodeValue); 
    } 
    else if (xmlStrcmp (node->name, XMLSTR("AdTitle")) == 0){ 
     char *nodeValue = (char *) node->children->content; 
     xmlFile->Ads->data->Inline->AdTitle = malloc (sizeof(char)); 
     strcpy (xmlFile->Ads->data->Inline->AdTitle, nodeValue); 
    } 
    else if (xmlStrcmp (node->name, XMLSTR("Category")) == 0){ 
     char *nodeValue = ""; 
     nodeValue = (char *) node->children->content; 
     xmlFile->Ads->data->Inline->Category = malloc (sizeof(char)); 
     strcpy (xmlFile->Ads->data->Inline->Category, nodeValue); 
    } 
    else if (xmlStrcmp (node->name, XMLSTR("Advertiser")) == 0){ 
     char *nodeValue = (char *) node->children->content; 
     xmlFile->Ads->data->Inline->Advertiser = malloc (sizeof(char)); 
     strcpy (xmlFile->Ads->data->Inline->Advertiser, nodeValue); 
    } 
    else if (xmlStrcmp (node->name, XMLSTR("Pricing")) == 0){ 
     char *nodeValue = (char *) node->children->content; 
     xmlFile->Ads->data->Inline->Pricing = malloc (sizeof(char)); 
     strcpy (xmlFile->Ads->data->Inline->Pricing, nodeValue); 
    } 
    else if (xmlStrcmp (node->name, XMLSTR("Expires")) == 0){ 
     char *nodeValue = (char *) node->children->content; 
     xmlFile->Ads->data->Inline->Expires = malloc (sizeof(char)); 
     strcpy (xmlFile->Ads->data->Inline->Expires, nodeValue); 
    } 
//  else if (xmlStrcmp (node->name, XMLSTR("Impression")) == 0){ 
//   char *nodeValue = (char *) node->children->next->content; 
//   xmlFile->Ads->data->Inline->Impression = malloc (sizeof(char)); 
//   strcpy (xmlFile->Ads->data->Inline->Impression, nodeValue); 
// 
//  } 
    else if (xmlStrcmp (node->name, XMLSTR("Creatives")) == 0){ 
     parseCreatives (doc, node->children, xmlFile); 
    } 

} while((node = node->next)); 

} 


void parseCreatives(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){ 

// Need to set up a new Creatives and assign it to the nested struct pointer 
VectorCreatives *Creatives; 
Creatives = (VectorCreatives *) malloc (sizeof(VectorCreatives)); 

VectorAds *Ads; 
Ads = (VectorAds *) malloc (sizeof(VectorAds)); 

xmlFile->Ads->data->Inline->Creatives = Creatives; 

vectorCreatives_init(xmlFile->Ads->data->Inline->Creatives); 

//*parseCreativesElements(doc, node->next, xmlFile); 

} 


void parseCreativesElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){ 

do { 

    // Loop through the creatives - find the individual Creatives 
    if (xmlStrcmp (node->name, XMLSTR("Creative")) == 0){ 

     // Various parses at this level 
     parseCreativeElements(doc, node->children, xmlFile); 
    } 

} while ((node = node->next)); 
} 

void parseCreativeElements(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){ 

do { 
    if (xmlStrcmp (node->name, XMLSTR("Linear")) == 0){ 
     // Linear branch 
     parseLinear(doc, node->children, xmlFile); 

    } else if (xmlStrcmp (node->name, XMLSTR("CompanionAds")) == 0){ 
     // Companion Ad branch 

    } 
} while ((node = node->next)); 

} 

void parseLinear(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){ 

do { 

    if (xmlStrcmp (node->name, XMLSTR("Duration")) == 0){ 

     struct daastCreative newCreative; 

     //*newCreative.linear.duration = node->children->content; 

     //*vectorCreatives_append(&xmlFile->Ads.data->Inline.Creatives, newCreative); 

    } else if (xmlStrcmp (node->name, XMLSTR("MediaFiles")) == 0){ 
     //parseMediaFiles(doc,node->children,xmlFile); 
    } 
} while ((node = node->next)); 

} 


void parseMediaFiles(xmlDocPtr doc, xmlNodePtr node, struct daastXML *xmlFile){ 

//* vectorMediaFiles_init(&xmlFile->Ads.data->Inline.Creatives.data->linear.MediaFiles); 

do { 

    // Store all occurrences of Media Files 
    if (xmlStrcmp (node->name, XMLSTR("MediaFile")) == 0){ 

     // Create a new Media File, and append 
     struct daastMediaFile newMediaFile; 

     newMediaFile.url = (char *) node->children->next->content; 

     newMediaFile.id = (char *)xmlGetProp(node, XMLSTR("id")); 
     newMediaFile.type = (char *)xmlGetProp(node, XMLSTR("type")); 
     newMediaFile.bitRate = (char *)xmlGetProp(node, XMLSTR("bitrate")); 
     newMediaFile.delivery = (char *)xmlGetProp(node, XMLSTR("delivery")); 

     //*vectorMediaFiles_append(&xmlFile->Ads.data->Inline.Creatives.data->linear.MediaFiles, newMediaFile); 

    } 
} while ((node = node->next)); 

} 


// *************************************************************** 
// *************************************************************** 
// *************************************************************** 
// *************************************************************** 


// Methods to manage collection (Ads) 

void vectorAds_init(VectorAds *vector) { 
    // initialize size and capacity 
    vector->size = 0; 
    vector->capacity = VECTOR_INITIAL_CAPACITY; 

    // allocate memory for vector->data 
    vector->data = malloc(sizeof(struct daastAd) * vector->capacity); 
} 

void vectorAds_append(VectorAds *vector, struct daastAd value) { 
    // make sure there's room to expand into 
    vectorAds_double_capacity_if_full(vector); 

    // append the value and increment vector->size 
    vector->data[vector->size++] = value; 
} 

struct daastAd vectorAds_get(VectorAds *vector, int index) { 
    if (index >= vector->size || index < 0) { 
    printf("Index %d out of bounds for vector of size %d\n", index, vector->size); 
    exit(1); 
    } 
    return vector->data[index]; 
} 

void vectorAds_set(VectorAds *vector, int index, struct daastAd value) { 
    // zero fill the vector up to the desired index 
    struct daastAd zero; 
    while (index >= vector->size) { 
    vectorAds_append(vector, zero); 
    } 

    // set the value at the desired index 
    vector->data[index] = value; 
} 

void vectorAds_double_capacity_if_full(VectorAds *vector) { 
    if (vector->size >= vector->capacity) { 
    // double vector->capacity and resize the allocated memory accordingly 
    vector->capacity *= 2; 
    vector->data = realloc(vector->data, sizeof(struct daastAd) * vector->capacity); 
    } 
} 

void vectorAds_free(VectorAds *vector) { 
    free(vector->data); 
} 


// Methods to manage Creatives Vector 

void vectorCreatives_init(VectorCreatives *vector) { 
    // initialize size and capacity 
    vector->size = 0; 
    vector->capacity = VECTOR_INITIAL_CAPACITY; 

    // allocate memory for vector->data 
    vector->data = malloc(sizeof(struct daastCreative) * vector->capacity); 
} 

void vectorCreatives_append(VectorCreatives *vector, struct daastCreative value) { 
    // make sure there's room to expand into 
    vectorCreatives_double_capacity_if_full(vector); 

    // append the value and increment vector->size 
    vector->data[vector->size++] = value; 
} 

struct daastCreative vectorCreatives_get(VectorCreatives *vector, int index) { 
    if (index >= vector->size || index < 0) { 
    printf("Index %d out of bounds for vector of size %d\n", index, vector->size); 
    exit(1); 
    } 
    return vector->data[index]; 
} 

void vectorCreatives_set(VectorCreatives *vector, int index, struct daastCreative value) { 
    // zero fill the vector up to the desired index 
    struct daastCreative zero; 
    while (index >= vector->size) { 
    vectorCreatives_append(vector, zero); 
    } 

    // set the value at the desired index 
    vector->data[index] = value; 
} 

void vectorCreatives_double_capacity_if_full(VectorCreatives *vector) { 
    if (vector->size >= vector->capacity) { 
    // double vector->capacity and resize the allocated memory accordingly 
    vector->capacity *= 2; 
    vector->data = realloc(vector->data, sizeof(struct daastCreative) * vector->capacity); 
    } 
} 

void vectorCreatives_free(VectorCreatives *vector) { 
    free(vector->data); 
} 


// Methods used to manage MediaFiles Vector 

void vectorMediaFiles_init(VectorMediaFiles *vector) { 
    // initialize size and capacity 
    vector->size = 0; 
    vector->capacity = VECTOR_INITIAL_CAPACITY; 

    // allocate memory for vector->data 
    vector->data = malloc(sizeof(struct daastMediaFile) * vector->capacity); 
} 

void vectorMediaFiles_append(VectorMediaFiles *vector, struct daastMediaFile value) { 
    // make sure there's room to expand into 
    vectorMediaFiles_double_capacity_if_full(vector); 

    // append the value and increment vector->size 
    vector->data[vector->size++] = value; 
} 

struct daastMediaFile vectorMediaFiles_get(VectorMediaFiles *vector, int index) { 
    if (index >= vector->size || index < 0) { 
    printf("Index %d out of bounds for vector of size %d\n", index, vector->size); 
    exit(1); 
    } 
    return vector->data[index]; 
} 

void vectorMediaFiles_set(VectorMediaFiles *vector, int index, struct daastMediaFile value) { 
    // zero fill the vector up to the desired index 
    struct daastMediaFile zero; 
    while (index >= vector->size) { 
    vectorMediaFiles_append(vector, zero); 
    } 

    // set the value at the desired index 
    vector->data[index] = value; 
} 

void vectorMediaFiles_double_capacity_if_full(VectorMediaFiles *vector) { 
    if (vector->size >= vector->capacity) { 
    // double vector->capacity and resize the allocated memory accordingly 
    vector->capacity *= 2; 
    vector->data = realloc(vector->data, sizeof(struct daastMediaFile) * vector->capacity); 
    } 
} 

void vectorMediaFiles_free(VectorMediaFiles *vector) { 
    free(vector->data); 
} 

#endif /* DAASTXML_C_ */ 

链接到XML:http://hearme.fm/ars.xml

+0

而内存指出'节点 - >孩子 - > content'将保持有效,你需要它的整个时间?在使用'xmlFile-> Ads-> data-> Inline-> AdSystem'之前,您不会“释放”它?你如何检查内存的内容?你在哪里检查它?'node-> children-> content' *已经*初始化为指向有效的分配内存?你为什么要投射指针?你能告诉我们结构的定义,或者至少是相关的部分吗?如果您删除了演员阵容,是否会收到编译器警告或错误?如果您启用更多警告(如果使用GCC或Clang,请添加'-Wall -Wextra -pedantic')? –

+0

您不应该直接'printf'字符串,如果字符串中有格式化字符,则可能会导致问题。 – horns

+0

我对C相当陌生,但我怀疑你在说什么,因为 - > AdSystem有效地指向由节点创建的值,当节点被释放时,值也是如此?那是对的吗? 我正在检查我的主要过程中的值,我首先解析xml文档,释放文档,然后返回xmlFile。 在这种情况下,分配此值的最佳方法是什么?我怀疑创建直接复制是正确的方法? –

OK,

我固定的错误,但它不”看看最干净的代码,也许有人可以建议,如果这是好的?

char *nodeValue = (char*) node->children->content; 
xmlFile->Ads->data->Inline->AdSystem = (char *) malloc (sizeof(char)); 
strcpy (xmlFile->Ads->data->Inline->AdSystem, nodeValue); 
+1

不,它不是。 1)你输入'malloc()'的结果,不要这样做。 2)你分配一个字节的内存,这已经被字符串末尾的'nul'使用。所以你必须为此清空字符串,而不是分配内存。您必须分配适量的内存。 –

+1

你需要分配足够的内存。应该是'malloc(strlen(nodeValue)+1);'。话虽如此,你需要在做这样的事情之前研究一下字符串的基础知识。 – Lundin

+1

回到最初的问题,有没有人有一个简单而有效的方式来分配节点值的值?这似乎比它应该更复杂 –

我固定的错误,但它看起来不干净的代码,也许如果这是好的 有人能指教?

char *nodeValue = (char*) node->children->content; 
xmlFile->Ads->data->Inline->AdSystem = (char *) malloc (sizeof(char)); 
strcpy (xmlFile->Ads->data->Inline->AdSystem, nodeValue); 

萨米Kuhmonen和伦丁已经指出的是,分配的大小是没有的。

回到最初的问题,有没有人有一个简单有效的 方式从节点值中分配一个值?这似乎更多 比它应该更复杂

你是对的;如果你有一个POSIX系统,上面可以通过使用strdup()被简化:

xmlFile->Ads->data->Inline->AdSystem = strdup((char *)node->children->content);