我有一个用 C 编写的大项目,其中大约有 2 行未发送的代码。
我在这个项目中有一个链表,我用它来存储程序的数据,在程序结束时我调用一个我编写的函数来释放链表的内存。但由于某种原因我收到此错误:
free(): invalid pointer
Aborted (code dumped)
我的链接列表分开在它自己的头文件中,所以在我的代码中向列表中添加节点并不重要,它们都只是调用
insertSymbol
来插入新列表,这样我就知道节点在堆内存。
这是我的SymbolTable.h 文件
#ifndef SYMBOL_TABLE_H
#define SYMBOL_TABLE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "constants.h"
/**
* a struct holding the SymbolTable information
*/
typedef struct SymbolTable {
char* symbol;
unsigned int identifier:2;
int value;
struct SymbolTable *next;
} SymbolTable;
extern SymbolTable* symbol_table;
/**
* Function insertSymbol
* ---------------------
* gets the symbol information (e.g. symbol name, identefier and value)
* and insert it to the symbol table
*
* @param symbol: string holding the symbol name
* @param identerfier: an integer holding the id of the symbol (e.g. .code, .mdefine or .data)
* @param value: the value of the symbol in the memory
*/
void insertSymbol(const char* symbol, const int identifier, const int value);
/**
* Function lookupSymbol
* ----------------------
* searching a symbol in the symbol table
*
* @param symbol: a string holding the symbol name to search
*
* @return a pointer to the symbol matching the name passed as an argument
*/
SymbolTable* lookupSymbol(const char* symbol);
/**
* Function freeSymbolTable
* ------------------------
* releasing the memory that was allocated to the symbol_table data structure
*/
void freeSymbolTable();
#endif
这是它的源代码:
#include "../headers/symbolTable.h"
SymbolTable* symbol_table = NULL;
void insertSymbol(const char *symbol, const int identifier, const int value)
{
SymbolTable **temp = &symbol_table;
while (*temp != NULL) {
temp = &(*temp)->next;
}
*temp = (SymbolTable*)calloc(1, sizeof(SymbolTable));
(*temp)->symbol = (char*)calloc(strlen(symbol) + 1, sizeof(char));
strcpy((*temp)->symbol, symbol);
(*temp)->identifier = identifier;
(*temp)->value = value;
(*temp)->next = NULL;
}
SymbolTable* lookupSymbol(const char *symbol)
{
SymbolTable *temp = symbol_table;
/* iterating over the symbol table and returning a pointer to the symbol if it was found otherwise returning null */
while (temp != NULL) {
if (strcmp(temp->symbol, symbol) == 0) {
return temp;
}
temp = temp->next;
}
return NULL;
}
void freeSymbolTable()
{
/* iterating over the symbol table and releasing the memory that was allocated for it */
SymbolTable *temp = NULL;
while (symbol_table != NULL)
{
temp = symbol_table;
symbol_table = symbol_table->next;
free(temp);
temp = NULL;
}
}
insertSymbol
,而不是自行添加,因此问题出在此处。您没有发布代码的其他部分,所以...
一些问题...
insertSymbol
可能 可以工作,但它非常复杂(始终使用 **
指针)。它看起来有问题/容易出错。freeSymbolTable
有一个错误:它不是免费symbol
(分配在insertSymbol
)。strdup
更容易使用。lookupSymbol
可以清理一下。return
语句(相对于底部的单个return
)。temp
(相对于更具描述性的名称)for
循环遍历链表更容易[而且,在我看来,更不容易出错]。这是重构后的代码。是有注释的。 (已编码但未编译或测试):
void
insertSymbol(const char *symbol, const int identifier, const int value)
{
// find the end/tail of the list
SymbolTable *prev = NULL;
for (SymbolTable *cur = symbol_table; cur != NULL; cur = cur->next)
prev = cur;
// get space for new node
SymbolTable *newsym = calloc(1, sizeof(SymbolTable));
// fill in node
// Note that strdup is much simpler to use
newsym->symbol = strdup(symbol);
newsym->identifier = identifier;
newsym->value = value;
// add to tail of non-empty list
if (prev != NULL)
prev->next = newsym;
// add as first element of list
else
symbol_table = newsym;
}
SymbolTable *
lookupSymbol(const char *symbol)
{
SymbolTable *match = symbol_table;
/* iterating over the symbol table and returning a pointer to the symbol
if it was found otherwise returning null */
for (; match != NULL; match = match->next) {
if (strcmp(match->symbol, symbol) == 0)
break;
}
return match;
}
void
freeSymbolTable(void)
{
/* iterating over the symbol table and releasing the memory that was
allocated for it */
SymbolTable *next;
for (SymbolTable *cur = symbol_table; cur != NULL; cur = next) {
// prevent use-after-free bug
next = cur->next;
// NOTE/BUG: this was missing!
free(cur->symbol);
free(cur);
}
symbol_table = NULL;
}