结构体指针无法访问二维char数组值,循环外内容为空
电路模拟程序的两个核心问题:params输出异常与内存错误
问题描述
我正在编写一个模拟电路的程序,定义了如下Gate与Node结构体:
typedef struct Gate { kind_t kind; int size; // size of DECODER and MULTIPLEXER char **params; // length determined by kind and size (CHANGED FROM INT TO CHAR) // includes inputs and outputs, indicated by variable numbers } Gate; typedef struct Node { Gate *data; struct Node *next; } Node;
在读取文件构建门电路链表的while循环内,printf可正常输出params数组内容,但循环外的for循环输出为空。相关逻辑代码如下:
// Linked list of gates & attributes while (fscanf(fp, "%16s", str) != EOF) { if (strcmp(str, "AND") == 0) { head = makeGate(fp, head, AND); length++; } else if (strcmp(str, "OR") == 0) { head = makeGate(fp, head, OR); length++; } else if (strcmp(str, "NAND") == 0) { head = makeGate(fp, head, NAND); length++; } else if (strcmp(str, "NOR") == 0) { head = makeGate(fp, head, NOR); length++; } else if (strcmp(str, "XOR") == 0) { head = makeGate(fp, head, XOR); length++; } else if (strcmp(str, "NOT") == 0) { //head = makeGate(fp, head, NOT); //length++; } else if (strcmp(str, "PASS") == 0) { //head = makeGate(fp, head, PASS); //length++; } else if (strcmp(str, "DECODER") == 0) { // } else if (strcmp(str, "MULTIPLEXER") == 0) { // } printf("%s\n", head->data->params[2]); } // plugs in values to circuit for (int i = 0; i < 3; i++) { printf("Stored string: %s\n", head->data->params[i]); }
makeGate函数实现如下:
Node *makeGate(FILE *fp, Node *head, kind_t inGate) { char str[17]; Node *new_node = (Node *)malloc(sizeof(Node)); // Node of linkedlist that contains gate structure new_node->data = (Gate *)malloc(sizeof(Gate)); // Gate structure that keeps information about a gate new_node->next = head; new_node->data->kind = inGate; new_node->data->size = 3; new_node->data->params = malloc(3 * sizeof(char*)); for (int i = 0; i < 3; i++) { new_node->data->params[i] = malloc(17 * sizeof(char)); } fscanf(fp, "%16s", str); new_node->data->params[0] = str; fscanf(fp, "%16s", str); new_node->data->params[1] = str; fscanf(fp, "%16s", str); new_node->data->params[2] = str; return new_node; }
此外,程序存在内存泄漏问题,尝试释放内存时会触发“释放未malloc地址”的错误,怀疑可能是节点丢失,但暂无解决思路。
问题1:params输出异常的原因与修复
核心原因
makeGate函数中,你为params的每个元素都分配了堆内存,但随后直接把栈上的str数组地址赋值给了params[i]。栈内存在函数返回后会被系统回收或被其他操作覆盖,所以循环内(makeGate刚执行完,栈内存尚未被破坏)能正常输出,但循环外栈内存已失效,导致输出为空或垃圾值。
修复方案
不要直接赋值指针,而是用strcpy把str的内容复制到已经分配好的堆内存中:
// 替换makeGate中赋值的部分 fscanf(fp, "%16s", str); strcpy(new_node->data->params[0], str); fscanf(fp, "%16s", str); strcpy(new_node->data->params[1], str); fscanf(fp, "%16s", str); strcpy(new_node->data->params[2], str);
这样params的每个元素都指向堆上保存的字符串副本,不会随栈内存失效而丢失。
问题2:内存泄漏与释放错误的原因与修复
核心原因
- 节点丢失:链表采用头插法构建,但如果未完整遍历整个链表就释放内存,会导致后续节点无法被访问,造成内存泄漏。
- 释放顺序错误:释放内存需要从内到外逐层进行:先释放
params的每个字符串,再释放params数组,接着释放Gate结构体,最后释放Node节点。顺序颠倒或跳过某一步,会触发内存错误。 - 错误释放栈地址:之前的代码中
params[i]指向栈内存,尝试释放这些地址会触发“释放未malloc地址”的错误,修复问题1后该情况会消失,但仍需注意释放顺序。
修复方案
编写专门的内存释放函数,遍历整个链表并逐层释放内存:
void freeCircuit(Node *head) { Node *current = head; while (current != NULL) { Node *next = current->next; // 释放params的每个字符串 for (int i = 0; i < current->data->size; i++) { free(current->data->params[i]); } // 释放params数组 free(current->data->params); // 释放Gate结构体 free(current->data); // 释放Node节点 free(current); current = next; } }
使用时直接调用freeCircuit(head)即可完整释放所有分配的内存,避免泄漏和释放错误。
内容的提问来源于stack exchange,提问作者Jack Bogart
相关产品推荐
相关产品推荐

