重置/清除指向结构

时间:2017-03-22 16:20:45

标签: c arrays struct

我是C的新手,我在重置或清除指向结构的全局指针数组时遇到了一些问题。 我需要接收一个文件(或更多)并在两个周期内读取它的行。 在阅读时我需要创建一个符号表(基本上是标签),然后用它来创建更多数据(将标签的位置导出到以十六进制值写入的文件中)。

我遇到的问题是我正在阅读两个文件。第一个文件被正确读取并且所有值都是正确的,但是当它尝试读取第二个文件时,我创建的表(数组)中的值仍然存在,即使我将它们释放。

我在头文件中声明了这个:(SIZE为30)

typedef struct symbol{
unsigned action :1;
unsigned external :1;
int address;    
char label[SIZE];
unsigned data_flag :1;
} symbol ; 

symbol *symbol_Table[SIZE] ;

添加新符号的示例:(这位于阅读功能中)

new_symbol =  malloc(sizeof(symbol));
strcpy(new_symbol->label, temp);
new_symbol->external = 0;
new_symbol->address = DC - tok_count; 
new_symbol->action = 0;
new_symbol->data_flag = 1;
add_symbol(new_symbol);
free(new_symbol);

添加功能,在另一个文件中:(更新

if(count == SIZE){
    **/*realloc the array size, increase it*/**
}

if(count < SIZE){
    symbol_Table[count] = malloc(sizeof(symbol));
    symbol_Table[count]->action = new_symbol->action;
    symbol_Table[count]->external = new_symbol->external;
    symbol_Table[count]->address = new_symbol->address;
    strcpy(symbol_Table[count]->label, new_symbol->label);
    symbol_Table[count]->data_flag = new_symbol->data_flag;

    /*printf("count: %d\n", count);*/
    return ++count;
}

return count;

在阅读循环结束时释放符号:( UPDATE

int i;
for(i = 0; i < count ; i++){
    free(symbol_Table[i]);
    symbol_Table[i] = NULL;
}

这是第一个文件第一个循环后的正确输出:

action: no | extern: yes | address: 0 | label L3 | data: no
action: no | extern: yes | address: 0 | label W | data: no
action: yes | extern: no | address: 100 | label MAIN | data: no
action: yes | extern: no | address: 106 | label LOOP | data: no
action: yes | extern: no | address: 119 | label END | data: no
action: no | extern: no | address: 0 | label STR | data: yes
action: no | extern: no | address: 7 | label LENGTH | data: yes
action: no | extern: no | address: 10 | label K | data: yes

以及第二个文件的第一个循环后的错误输出:( UPDATE

action: yes | extern: no | address: 100 | label MAIN | data: yes
action: no | extern: yes | address: 0 | label W | data: yes
action: yes | extern: no | address: 108 | label LOOP | data: yes
action: no | extern: no | address: 0 | label STR | data: yes
action: no | extern: no | address: 3 | label K | data: yes

应该是:

action: yes | extern: no | address: 100 | label MAIN | data: no
action: no | extern: yes | address: 0 | label W | data: no
action: yes | extern: no | address: 108 | label LOOP | data: no
action: no | extern: no | address: 0 | label STR | data: yes
action: no | extern: no | address: 3 | label K | data: yes

几个问题:

  1. 使用后有没有办法清理清单?然后重新使用相同的列表来获取新值?并避免内存泄漏。
  2. 这个想法与数组只是浪费空间,我应该尝试使用链接列表吗?我担心我必须再次写完整个项目,时间不在我身边..
  3. 更新后

    1. 当我到达终点时,如何重新分配更多内存以增加阵列的大小?
    2. 如果我误用了一个术语,我会道歉,我正在用不同的语言学习C.

2 个答案:

答案 0 :(得分:1)

即使你正在释放你的结构,你的数据也不会立即被覆盖,因为堆分配器并不是必需的;它只是记下你释放的空间是可用的。您应该更进一步,并在释放它们之后将数组的每个索引设置为NULL。这实际上会从阵列中删除它们。

现在,我在使用数组时会非常谨慎。您已指定了一个尺寸,但您并未在添加功能中强制执行该尺寸。

如果通过使用malloc交换数组以使用动态内存,并且稍后在程序中达到大小约束,则可以使用realloc分配更多空间(这基本上允许您实现ArrayList而不使用扰乱了你计划的其余部分的实施。

要为数组初始分配空间,请尝试:

symbol **symbol_Table = (symbol *) malloc(sizeof(symbol *) * SIZE);

注意: malloc只能从里面方法调用。因此,在文件的顶部,您可以声明您的变量:

symbol **symbol_Table;

然后,在使用它之前,您应该在main()方法中定义它:

symbol_Table = (symbol **) malloc(sizeof(symbol **) * SIZE);

注意malloc语句中的表示法 - 你需要乘以它的大小 具有符号指针大小的数组,因为malloc获取要分配的字节数。 sizeof(symbol *)为您提供单个symbol指针的大小。

另外:为了使用realloc,symbol_Table的初始分配应该是malloc / calloc / realloc返回的,或者是NULL。

如果您只是尝试将重新分配弹出到if语句中,请尝试:

static size_t current_size = SIZE;

if(count == current_size) {
  current_size = current_size << 1;
  symbol_Table = (symbol *)realloc(symbol_table, sizeof(symbol *) * current_size);
}

if(count < current_size) {
  // ... the rest of the code continues here

关于current_size << 1的位是左移位 - 它有效地将current_size乘以2。

静态变量在函数调用之间保留其值。因此,如果我在调用函数一次时更改它,下次调用函数时,变量将具有我在上一次调用中设置的值。静态变量的原因是,如果增加数组的大小,则必须在调用之间保存current_size的值,并且必须在某处存储数组的大小。存储它的最佳位置是在一个函数中,其中数组的实际大小很重要 - 它是唯一可以放大的地方。一个全局变量也可以正常工作。

要在最后释放符号表:

int i;
for(i = 0; i < count ; i++){
  if(symbol_Table[i] != NULL) // Important - we cannot free NULL
  {
    free(symbol_Table[i]);
    symbol_Table[i] = NULL;
  }
}
count = 0; // Important - if we are deleting everything in the array, we
           // need to make sure we reset the count for our next delete
           // operation

答案 1 :(得分:0)

你的问题是(IMO)SIZE是一个常数。如果你使它变量,你可以在需要时调整符号表的大小。

最干净的方法是将指针数组与大小一起存储在某个包络结构中,如:

struct symbol{
        unsigned action :1;
        unsigned external :1;
        unsigned data_flag :1;
        int address;
        char label[SIZE];
        } symbol ;


struct symtab{
        unsigned size;
        unsigned used;
        struct symbol **table; /* used as an array of pointers */
        };

        /* global: for fun */
struct symtab thetab = {0,0,NULL};

int resize_the_thing(struct symtab *sp, unsigned new_size)
{
struct symbol **newtable;

        /* Note: realloc takes care of copying, too ...*/
newtable = realloc (sp->table, new_size * sizeof sp->table[0]);

if (!newtable) { /* handle error */
        return -1;
        }

sp->table = newtable;
        /* TODO: you need to check the case new_size < size here, too */
sp->size = new_size;
return 0; /* no_error */
}

/* typical usage: */

if (thetab.used >= thetab.size && resize_the_thing( &thetab, 12345)) {
        /* report error */
        }

thetab.table[thetab.used++] = new_symbol(...);