【问题标题】:Getting an segmentation fault (core dumped) error in Ubuntu在 Ubuntu 中出现分段错误(核心转储)错误
【发布时间】:2017-04-05 09:51:28
【问题描述】:

我正在尝试构建一个用作汇编程序的程序,它将获取文件名作为命令行参数并将它们转换为机器代码。

程序编译得很好,使用 1 个文件名运行正常,但是当我尝试使用多个文件名运行时,第一次迭代后出现错误。

我认为Clear() 函数可能有问题(它会清除上一次迭代中分配的所有数据),但不确定原因。请注意,这是部分内容,但正如我所说,除非使用多个文件,否则程序将运行。

struct symbolStruct { // a structure which is used to absorb info about a tag, its place in memory and related flags
    char *name;
    int place;
    unsigned int isEntry : 1;
    unsigned int isData : 1;
    unsigned int isExternal : 1;
    struct symbolStruct *next;
};

typedef struct { // a structure which is used to absorb info about the operand structure of an instruction line
    unsigned int numOfOperands : 2;
    unsigned int addrMethSou : 2;
    unsigned int addrMethDest : 2;
    unsigned int operation : 4;
    unsigned int extraWords : 2;
    char *firstOperand;
    char *secondOperand;
} OperandType;

typedef struct {
    unsigned int row : WORD_SIZE;
} int15;

struct MachineCode { // a structure which is used to absorb machine code lines, and their location in the assembly file
    unsigned int row : WORD_SIZE;
    unsigned int line;
    OperandType *structure;
    struct MachineCode *next;
};

struct DataCode { // a structure which is used to absorb data and string elements (signed numbers and ascii characters)
    unsigned int row : WORD_SIZE;
    struct DataCode *next;
};

struct Operation { /* the main operation structure, contains pointers to all used lists, the ic and dc counters, the
    current line number which is dealt with and the error flag. */
    unsigned int ic;
    unsigned int dc;
    struct symbolStruct *externHead; // a pointer to a linked list of extern tags used in the assembly file, and their locations
    struct symbolStruct *symbolHead; // a pointer to a linked list of all tags
    struct DataCode *dataHead; // a pointer to a linked list of all data/string elements
    struct MachineCode *machineHead; // a pointer to a linked list of all machine code rows
    int linenumber;
    unsigned int errorflag : 1; // raised in case of an error which triggered a warning
};

#include "header.h"

void FirstRun(struct Operation*, char *);
void DataUpdate(struct symbolStruct*,int);
void SecondRun(struct Operation *, char *);
void Clear(struct Operation *);

int main(int argc, char *argv[]) {
    int i;
    struct Operation programCore = {0,0,NULL,NULL,NULL,NULL,0,0};
    for(i=1;i<argc;i++) {
        char *fn = argv[i];
        FirstRun(&programCore,fn);
        DataUpdate(programCore.symbolHead,programCore.ic+INSTRUCTION_OFFSET);
        SecondRun(&programCore,fn);
        Clear(&programCore);
        programCore.symbolHead = programCore.externHead = programCore.dataHead = programCore.machineHead = NULL;
    }
    if(argc < 2) {
        fprintf(stderr,"No files selected.\n");
    }
    return 0;
}

/*Used to empty the linked lists and allocated memory after the program has finished one iteration. */
void Clear(struct Operation *programCore) { 
    /*f(pointer name) is there to hold a pointer to the allocated memory which is about to be flushed. */
    struct MachineCode *machineHead = programCore->machineHead, *fMachineHead; 
    struct DataCode *dataHead = programCore->dataHead, *fDataHead; 
        struct symbolStruct *externHead = programCore->externHead, *fExternHead;
    struct symbolStruct *symbolHead = programCore->symbolHead, *fSymbolHead;
    while(machineHead != NULL) {
            fMachineHead = machineHead;
        machineHead = machineHead->next;
        if(fMachineHead->structure != NULL) {
            if(fMachineHead->structure->numOfOperands == 2)
                free(fMachineHead->structure->secondOperand);
            if(fMachineHead->structure->numOfOperands > 0)
                free(fMachineHead->structure->firstOperand);
            free(fMachineHead->structure);
        }
        free(fMachineHead);
    }
    while(dataHead != NULL) {
        fDataHead = dataHead;
        dataHead = dataHead->next;
        free(fDataHead);
    }
    while(externHead != NULL) {
        fExternHead = externHead;
        externHead = externHead->next;
        free(fExternHead->name);
        free(fExternHead);
    }
    while(symbolHead != NULL) {
        fSymbolHead = symbolHead;
        symbolHead = symbolHead->next;
        free(fSymbolHead->name);
        free(fSymbolHead);
    }
    programCore->ic = programCore->dc = programCore->linenumber = programCore->errorflag = 0;
}

【问题讨论】:

  • 你还没有说你的代码在哪里崩溃——在调试器中运行它,你会看到它发生在哪一行。也可能会向您展示您需要修复的内容。
  • [off-topic] 就个人而言,我会使用(可变大小)数组,而不是表的链接列表。
  • 为了便于阅读和理解:1) 通过一个空行分隔代码块(for、if、else、while、do...while、switch、case、default)。 2) 用 2 或 3 个空行分隔函数(保持一致) 3) 遵循公理:每行只有一个语句,并且(最多)每个语句一个变量声明。
  • 虽然“隐式转换”功能可以节省代码,但不应依赖它。 NULL 和 0 的含义有很大的不同(尽管位值可能相同。
  • 当命令行参数有问题时,(比如没有)代码应该输出USAGE语句到stderr,类似:fprintf( stderr, "USAGE: %s &lt;srcFileName1&gt; [[srcFileNameN]]\n", argv[0] );这样的语句通常后面跟着exit( EXIT_FAILURE );

标签: c linux struct error-handling segmentation-fault


【解决方案1】:

您不会释放和取消上下文结构 (programCore) 中的链接列表。我怀疑你在使用指针来释放内存块。

这一行只复制指针:

struct MachineCode *machineHead = programCore->machineHead;

while() 循环未清除 programCore-&gt;machineHead

要修复它,直接在头部运行:

while(programCore->machineHead != NULL)
{
    ...
}

【讨论】:

  • 如果我这样做,它不是只清除头部,而不清除它之后的节点吗?如何确保整个列表都被清除,并且头部无效?
  • 我还想确保字符串 firstOperand 和 secondOperand 都被清除。
  • 我认为该程序确实是我没有使头无效的事实,因为稍后我有一个函数可以检查头 == NULL,如果是,则将内存分配给新节点案例。
  • 问题*该死的
【解决方案2】:

好吧,摆脱

   if(fMachineHead->structure->numOfOperands == 2)
         free(fMachineHead->structure->secondOperand);
   if(fMachineHead->structure->numOfOperands > 0)
         free(fMachineHead->structure->firstOperand);

我已经设法解决了这个错误,但现在我得到了一个新的 -

main.c:242:13: error: request for member ‘symbolHead’ in something not a structure or union
main.c:242:38: error: request for member ‘externHead’ in something not a structure or union
main.c:243:13: error: request for member ‘dataHead’ in something not a structure or union
main.c:244:13: error: request for member ‘machineHead’ in something not a structure or union

参考下一行-

        programCore.symbolHead = programCore.externHead = programCore.dataHead = programCore.machineHead = NULL;

我写的方式有问题吗? (显然是的,但我只是没看到)。

【讨论】:

  • 问题是这些字段有些是unsigned int,有些是int,并且操作是从右到左执行的,所以一些unsigned int值是从int值分配的。建议将每个作业写成单独的语句。
  • 问题是protramCore是一个指针,所以必须使用-&gt;而不是. ALSO,每个指针都是不同的类型,操作是从右到左执行的,并且不能分配不同类型的指针。建议将每个作业写成单独的语句。
【解决方案3】:

再次更改了 clear() 函数,现在似乎可以正常工作了。

    /*Used to empty the linked lists and allocated memory after the program has finished one iteration. */
void Clear(struct Operation *programCore) { 
    /*f(pointer name) is there to hold a pointer to the allocated memory which is about to be flushed. */
    struct MachineCode *machineRowPointer = programCore->machineHead, *fMachineRow; 
    struct DataCode *dataRowPointer = programCore->dataHead, *fDataRow; 
        struct symbolStruct *externSymbolPointer = programCore->externHead, *fExtern;
    struct symbolStruct *symbolPointer = programCore->symbolHead, *fSymbol;
    if(machineRowPointer != NULL) {
        while(machineRowPointer != NULL) {
            if(machineRowPointer->structure != NULL)
                free(machineRowPointer->structure);
            fMachineRow = machineRowPointer;
            machineRowPointer = machineRowPointer->next;
            free(fMachineRow);
        }
        programCore->machineHead = NULL;
    }
    if(dataRowPointer != NULL) {
        while(dataRowPointer != NULL) {
            fDataRow = dataRowPointer;
            dataRowPointer = dataRowPointer->next;
            free(fDataRow);
        }
        programCore->dataHead = NULL;
    }
    if(externSymbolPointer != NULL) {
        while(externSymbolPointer != NULL) {
            fExtern = externSymbolPointer;
            externSymbolPointer = externSymbolPointer->next;
            free(fExtern->name);
            free(fExtern);
        }
        programCore->externHead = NULL;
    }
    if(symbolPointer != NULL) {
        while(symbolPointer != NULL) {
            fSymbol = symbolPointer;
            symbolPointer = symbolPointer->next;
            free(fSymbol->name);
            free(fSymbol);
        }
        programCore->symbolHead = NULL;
    }
    programCore->ic = programCore->dc = programCore->linenumber = programCore->errorflag = 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    相关资源
    最近更新 更多