【问题标题】:Why am I getting this error: dereferencing pointer to incomplete type为什么会出现此错误:取消引用指向不完整类型的指针
【发布时间】:2011-12-21 11:49:37
【问题描述】:

我正在做一个课堂项目,可能是最糟糕的指令,我们必须实现一个简单的调度程序。虽然 C 编程不是课程的先决条件,但这是调度程序的语言,我不是一定是 C 程序员..

无论如何,我正在尝试通过打印任务来调试它,以便我可以通过程序对其进行跟踪,但我不断收到以下编译时错误:

schedule.c:61:48: 错误:取消引用指向不完整类型的指针

这是task_struct 定义:

struct task_struct
{
    struct thread_info *thread_info;        
    int prio, static_prio, normal_prio;     
    unsigned long sleep_avg;            
    unsigned long long last_ran;            
    unsigned long long timestamp;           
    unsigned long long sched_time;          
    unsigned int time_slice, first_time_slice;  
    struct list_head run_list;          
    struct sched_array *array;          
    enum sleep_type sleep_type;         
    int need_reschedule;                
};

我试图在里面调试的函数:

void initschedule(struct runqueue *newrq, struct task_struct *seedTask)
{
printf("Inside initschedule()\n");

printf("%s - TEST \n", (seedTask)->thread_info->processName); //causes compiler error

/* initialize runqueue and current task */
rq = newrq;
current = NULL;

/* allocate memory for runqueue schedule arrays */
rq->active = (struct sched_array*)malloc(sizeof(struct sched_array));
rq->expired = (struct sched_array*)malloc(sizeof(struct sched_array));

/* initialize schedule arrays */
INIT_LIST_HEAD(&rq->active->list);
INIT_LIST_HEAD(&rq->active->list);

/* activate task in scheduler */
activate_task(seedTask);

}

最奇怪的是,当我在调用上述函数的方法中使用相同的printf(...) 时,它可以工作,但在我传入seedTask 的函数中却不行。

所以基本上,我想知道为什么会出现这个错误?

【问题讨论】:

    标签: c linux scheduling


    【解决方案1】:

    这是因为函数 initschedule 只看到了 struct task_struct 的声明,没有看到它的定义。大概调用initschedule 的函数已经看到了定义,因此可以取消引用指向它的指针。

    所以对于initschedule,它是一个不完整的类型,它只能传递指向它的指针,但实际上不能取消引用这些指针。

    只需确保在 schedule.c 中包含定义该结构的标头即可。

    编辑

    似乎是另一个不完整的定义导致了这种情况:thread_info。这与上面解释的基本问题相同,但您必须包含定义thread_info 的标头。

    【讨论】:

    • task_struct 定义在 schedule.h 中,它包含在 schedule.c 中,其中包含 initschedule 函数。
    • @shuniar:此答案不正确,因为您在主 Q 中提供的信息不足,但随后在评论中添加了此信息。检查我的答案,它解释了错误的原因和内容是解决方案。
    • @Als 这只是一个冗长的版本,还建议包含标题。我坚持我的答案。
    • 恐怕是错的。正如OP已经说过他的schedule.c已经包含schedule.h,它定义了struct task_struct(你的回答暗示了同样的事情)。它实际上没有解决任何问题。因为OP需要包含定义struct thread_info的标题。
    【解决方案2】:

    为什么会出现此错误:取消引用指向不完整类型的指针?

    您添加以下行而不是包含头文件:

    struct task_struct;
    

    Forward 声明了task_struct,这意味着对于编译器它是一个不完整类型。对于不完整的类型,人们不能创建它的变量或做任何需要编译器知道task_struct 的布局的事情,或者除了task_struct 只是一种类型这一事实之外。 即:编译器不知道它的成员是什么以及它的内存布局是什么。
    但是由于指向所有对象的指针只需要相同的内存分配,因此您可以在仅将 Incomplete 类型作为指针引用时使用前向声明。

    注意,前向声明通常用于类的循环依赖。

    前向声明对于如何进一步使用不完整类型有其自身的限制。
    使用不完整类型,您可以:

    • 将成员声明为指向不完整类型的指针。
    • 声明接受/返回不完整类型的函数或方法。
    • 定义函数或方法接受/返回指向不完整类型的指针(但不使用其成员)。

    对于不完整类型,您不能:

    • 用它来声明一个成员。
    • 使用此类型定义函数或方法。

    建议的解决方案:
    这里的问题是因为在函数initschedule里面你尝试访问struct task_struct的成员,即:

    (seedTask)->thread_info->processName
    

    所以这里的编译器需要知道成员thread_info的定义。您需要在schedule.c 中包含定义struct thread_info 的标头。

    为什么它在schedule.h 中正常工作?
    因为该头文件仅将 struct thread_info 作为指针引用而没有其成员,而 schedule.c 则引用。

    【讨论】:

    • 谢谢,在我将 privatestructs.h 包含在其中定义了 thread_info 结构之后,这才有效。
    【解决方案3】:

    当您定义initschedule 时,task_struct 仍然是一个不完整的类型。您需要确保 struct task_struct 的整个定义在编译 initschedule 时可见。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-06
      • 2018-05-31
      • 2017-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多