【问题标题】:C Memory free in loop error -> invalid read of size 1C Memory free in loop error -> 大小为 1 的无效读取
【发布时间】:2019-05-31 05:07:05
【问题描述】:

我对循环中的malloc'ed char 指针的free() 有疑问。

char *x=malloc(30) 中,我存储了一个字符串,我用add(x,queue) 将其推入堆栈。问题是我每次迭代都malloc-ing 它,所以我需要在每次迭代中free 它,否则我在valgrind 中有内存泄漏。但是如果我将free(x); 放在while 循环的末尾,valgrind 就会遇到strcmp 的问题:

Invalid read of size 1
at 0x403045D: strcmp

by 0x048871: main(main.c 149) = else if(!strcmp(x,l))
address is 0 bytes inside block of size 30 free d

by 0x80488b8: main(main.c 164) = free(x);
block was allocked at
at 0x402c17c:malloc by main(main.c 129) =char *x=malloc(30);

这很奇怪,因为在另一个分配之前我不需要那个char *x。 有没有办法以不同的方式分配它?

while ((a = getchar()) != EOF) {
    if (a == '<'){
        act = 1;
    }
    if (act == 1) {
        char *x=malloc(30);
        scanf("%29[^>]s",x);

        if(*x=='/'){

            void *l;
            l=pop_from_queue(queue);

            if(l==NULL)
                valid=1;
            else if(!strcmp(x+1,l))
                valid=0;
            else
                valid=1;

            act=0;
        }else{
            push_to_queue(queue,x); //push to stack
            count++;
            act=0;

        }
        free(x);       
     }
}

初始化栈:

typedef struct {
  void **data;
  int head;
  int size;
  int count;

} queue_t;

queue_t* create_queue(int capacity){
  queue_t *queue=calloc(sizeof(queue_t),sizeof(queue_t));
  queue->head=0;
  queue->data=calloc(capacity+10,sizeof(void*));
  queue->count=0;
  queue->size=capacity+1;
  return queue;
}

弹出功能:

void* pop_from_queue(queue_t *queue){

  if(queue->count==0)
    return NULL;
  else
    queue->count--;

  if(queue->head<0)
    return NULL;

  if(queue->head!=0)
    queue->head--;

  return queue->data[queue->head];

}

推送功能:

bool push_to_queue(queue_t *queue, void *data){
  if(queue->count==queue->size){
    queue->size+=10;
    queue->data=realloc(queue->data,queue->size*sizeof(void*));
  }
  queue->data[queue->head++]=data;
  queue->count++;

  return true;
}

【问题讨论】:

  • 我也鼓励你在(*x=='/') 时删除 x 以防止内存泄漏,并帮助不要做x++strcmp(x+1,l)
  • 没错,但我永远不会说超过 20 个字。
  • 我需要 x 用于 strcmp(x,l) 所以我不能删除它。 :( 那个 x++; 是用来从 x 中删除第一个字符的,所以我可以将它与堆栈中弹出的字符串进行比较
  • 所以我需要释放(x++)?或更改 x++;
  • @Dzoey 正如我所说,最小的变化是删除 x++; 并将 strcmp 修改为 strcmp(x+1,l),这样你就可以在之后 free(x) 而不必做free(x-1)不是很清楚

标签: c memory stack malloc


【解决方案1】:

在取消引用 x 之前,您没有验证 scanf() 是否实际处理了任何数据。

如果scanf() 不读取任何数据并将其存储在x 中,则从x 读取的任何数据都将无效。

【讨论】:

    【解决方案2】:

    你不能在push_to_queue(queue,x);之后做free(x);,你必须在free(x);之后才if(*x=='/')

    因为您释放了推送的值,所以当您弹出它时,您会获得一个已经空闲的内存,并且该内存被 strcmp

    使用

    这么简单我以前没见过!

    注意:无论 strcmp

    的结果如何,如果不是 NULL,则需要释放通过 pop 获得的值

    【讨论】:

    • 没错。但是有没有办法在while循环结束后释放所有mallocked X?现在我没有收到 valgrind 错误,但我有 1 个泄漏的块,每个 X 被锁定。我是否需要将它们存储在其他地方以便在循环后删除它们?
    • @Dzoey 之后做类似的事情:void *l; while((l = pop_from_queue(queue)) != 0) free(l);
    • 非常感谢。它现在可以工作了。我还需要释放(l);在 if(*x=='/') 条件下。 GJ
    • @Dzoey 是的,我说你这样做 ;-) 我也鼓励你简化你的代码,例如使用变量 act 是没用的
    猜你喜欢
    • 1970-01-01
    • 2014-04-19
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-17
    • 2020-09-30
    • 2014-11-30
    相关资源
    最近更新 更多