【问题标题】:C program acting weirdC程序行为怪异
【发布时间】:2016-01-16 21:48:36
【问题描述】:

我已经开始在 C 中实现一个循环队列,并且我有以下代码行:

#include <stdio.h>
#include <stdlib.h>
#include "cirq.h"

//allocate a circular queue
cirq cq_alloc(void){
  cirq cq = NULL;
  element *head;
  element *tail;

  if((head = malloc(sizeof(struct element*))) &&
      (tail = malloc(sizeof(struct element *)))){
    head->content = 0; // head node keeps track of size.
    tail->content = NULL;
    head->next = tail;
    tail->next = head;
    cq = &head;
  } else {
    printf("ERROR: No space for more cqueues.\n");
  }
  return cq;
}

int cq_size(cirq q){
  return (int)(*q)->content;
}

int main(){
  cirq q = cq_alloc();
  printf("Size of element ptr %lu\n", sizeof(struct element *));
  printf("%d\n", cq_size(q));
  return 0;
}

现在,当我编译并运行这个程序时,已经注释掉了main 中打印出sizeof(struct element *)) 的行,程序运行良好,我得到了正确的队列大小,0。当我把行留在,struct 的大小被打印出来,但之后我得到一个segmentation fault: 11。另外,为了清楚起见,struct elementvoid *datastruct element *next 字段。添加打印内容的行怎么会如此改变程序的行为?

编辑:cirq.h

#ifndef CIRQ_H
#define CIRQ_H
typedef struct element **cirq; // cirq handle

typedef struct element {
  void *content;
  struct element *next;
} element;

extern cirq cq_alloc(void);// allocate a queue
extern int cq_size(cirq q);// return the size of a queue
extern void cq_enq(cirq q, void *value);// add a value to the queue
extern void *cq_deq(cirq q);// dequeue and return a queue value
extern void *cq_peek(cirq q);// return the value at the queue head
extern void cq_rot(cirq q);// requeue the head element at the tail
extern void cq_free(cirq q);// return all space allocated to queue
#endif

【问题讨论】:

  • 这被称为未定义的行为,它是一个bi*h。您的 if ((head = malloc() ... 可能会导致内存泄漏。这不是很好的风格,也没有提高可读性,实际上很糟糕(*这实际上是建设性的,这是建议)。
  • 不完整,请阅读How to Ask
  • 你能说明criqelement的定义吗? (如果不是太多:cirq.h的全部内容)
  • 当然!我在问题的最后提到了elementcirq 被定义为struct element **cirq

标签: c gcc


【解决方案1】:

这是难闻的气味:

if((head = malloc(sizeof(struct element*))) &&

您正在分配 指针 的大小。我认为您的意思是 malloc 结构本身...?

【讨论】:

  • 你说得对,我的意思是 malloc 结构本身!
【解决方案2】:

cirq 是什么并不重要,问题在于您返回本地对象的地址。

这里

cq = &head;

导致未定义的行为,因为这是指针head 的地址,它仅在函数本地存储,当函数返回时,它被释放并因此无效。在其他地方(函数之外)使用它是未定义的行为

另外,不要typedef 指针。千万不要那样做,让代码阅读器知道它是一个指针

【讨论】:

  • 我希望得到更好的答案!我创建了headtail 全局变量,未定义的行为停止了。谢谢朋友!
  • @modsoussi 这就像说把头放在煤气炉里治好了你的头痛。如果你想要两个 'circ' 对象会发生什么???
  • @modsoussi 糟糕的解决方案!此外,您无法判断未定义的行为是否停止,它是未定义的,有时您甚至不知道它的存在。
  • @Roddy 将cirq 定义为structheadtail 字段而不是双指针是否更有意义?或者@iharob 只是返回&amp;head
猜你喜欢
  • 2017-01-17
  • 2016-06-14
  • 2020-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
相关资源
最近更新 更多