free():无效指针中止(代码转储)(ubuntu C)

问题描述 投票:0回答:1

我有一个用 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
,而不是自行添加,因此问题出在此处。

c ubuntu malloc free calloc
1个回答
0
投票

您没有发布代码的其他部分,所以...

一些问题...

  1. 您的
    insertSymbol
    可能 可以工作,但它非常复杂(始终使用
    **
    指针)。它看起来有问题/容易出错。
  2. freeSymbolTable
    有一个错误:它不是免费
    symbol
    (分配在
    insertSymbol
    )。
  3. strdup
    更容易使用。
  4. lookupSymbol
    可以清理一下。
  5. 应尽可能避免使用“非标准”
    return
    语句(相对于底部的单个
    return
    )。
  6. 大量使用
    temp
    (相对于更具描述性的名称)
  7. 使用
    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;
}
© www.soinside.com 2019 - 2024. All rights reserved.