C语言 指针无故改变值?

d6kp6zgx  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(82)

我必须在Flex/Yacc上做这个项目,在那里我必须计算一个Insiemistic表达式的抽象树。但真实的问题在C代码中。
我创建了这个函数,它创建了一个节点:

node_t * createNode(node_content_t nodecontent, int nodetype){
    node_t *newNode = (node_t *) malloc(sizeof(node_t * ));
    if(nodetype == 0){
        newNode->content = (node_content_t)strdup(nodecontent.string);
    }
    else
        newNode->content = nodecontent;
    newNode->type = nodetype;

    newNode->leftChild = NULL;
    newNode->rightChild = NULL;
    printf("Right Child in createNode: %p\n", newNode->rightChild);
    return newNode;
}

正如你所看到的,left和right child都被初始化为null。但是,当我试图打印右子函数的指针值时,它改变了值(通常为0x 23或0x 53),导致分段错误。
node_t和node_content_t定义如下

typedef union{
        char* string;
        char singleletter;
    }node_content_t;

    typedef struct node node_t;
    struct node{
        node_content_t content;
        int type; //0 for string, 1 for char
        node_t *leftChild;
        node_t *rightChild;
    };

当我试图在createNode中打印指针时,结果是0x 0,我在这个函数printNode中打印它,这应该打印整个树:

void printNode(node_t *n, size_t indent) {
    
    char *indentation = malloc(sizeof(char) * indent);
    for (size_t i = 0; i < indent; ++i) {
        indentation[i] = ' ';
    }
    printf("LeftChild: %p\n", n->leftChild);
    printf("RightChild: %p\n", n->rightChild);
    switch (n->type) {
        case 0: printf("%s%s\n", indentation, n->content); break;
        case 1: printf("%s%c\n", indentation, n->content); break;
    }
    if (n->leftChild != NULL){
        printNode(n->leftChild, indent+2);
    }
    if (n->rightChild != NULL){
        printf("RightChild: %p\n", n->rightChild); //there
        printNode(n->rightChild, indent+2);
    }
    printf("Non ci sono figli\n");

}

就像我说的,值改变了,所以函数不起作用,有什么想法吗?如果不在函数addChild中,我不会修改rightChild的值:

void addChild(node_t *parent, node_t *child) {
    printf("Addchild\n");
    printf("Right Child in createNode: %p\n", parent->rightChild);
    if(parent->leftChild == NULL)
        parent->leftChild = child;
    else if(parent->rightChild == NULL && strcmp(parent->content.string, "co") != 0 ){
        parent-> rightChild = child;
        printf("Aggiunto figlio destro\nContent: %c\nType: %d\n", child->content, child->type);
    }
    else
        printf("Error during child adding\n");
}
v8wbuo2f

v8wbuo2f1#

问题一:

node_t *newNode = (node_t *) malloc(sizeof(node_t * ));

1.这为node_t *分配了足够的空间;不是你想要的node_t结构。
1.铸造是不必要的(可能是有害的。
1.最好使用变量的 name 而不是它的 type(减少将来的维护)。

  1. malloc()可能会失败。习惯检查返回值。养成习惯吧!
node_t *newNode = malloc( sizeof *newNode ); // cleaner
if( newNode == NULL ) { /* handle error condition */ }

问题二:

void printNode(node_t *n, size_t indent) {
    
    char *indentation = malloc(sizeof(char) * indent); // <== never free'd
    for (size_t i = 0; i < indent; ++i) { // unnecessary...
        indentation[i] = ' ';
    }
    printf("LeftChild: %p\n", n->leftChild);
    printf("RightChild: %p\n", n->rightChild);
    switch (n->type) {
        case 0: printf("%s%s\n", indentation, n->content); break;
        case 1: printf("%s%c\n", indentation, n->content); break;
    }
  1. indentation在每次调用这个函数时都被分配,并且它永远不会被free()'d。
    内存泄漏(加速分配失败的发生。)
  2. indentation不是 *null终止的 *,并且不能被视为C字符串。
    摆脱执行分配的行,并利用printf()的功能。例如:
printf( "%*s%s\n", indent, "", n->content ); break;

%*s从下一个参数中获取 * 字段宽度说明符 *,在本例中为indent。然后,它将字符串打印到一个如此宽的字段中,在本例中为""。结果是每行上所需空格数的 * 前缀 *。

ffscu2ro

ffscu2ro2#

问题在于malloc()调用:node_t *newNode = (node_t *) malloc(sizeof(node_t * ));只分配指针的大小。
要求解,请将其更改为node_t *newNode = malloc(sizeof *newNode);

相关问题