malloc的奇怪行为

时间:2014-12-03 10:15:00

标签: c linux struct malloc system

我正在尝试动态初始化队列。这是我的功能。

typedef struct{
    int size;
    int max_size;
    short * eles;
} queue;

void dump_queue(queue *q)
{
    //print a bunch of information
}

void init_queue(queue *q, int max_size)
{
    q = (queue)malloc(sizeof(queue));
    q->size = 0;
    q->max_size = max_size;
    q->eles = (short *)malloc(max_size * sizeof(short));
    int i;
    for(i = 0; i < max_size; i++)
        q->eles[i] = -1;
    dump_queue(q);
}

task_queue是一个全局变量。例程的结构如下:(不是确切的代码)

//globally defined here but not initialized 
queue * task_queue;
void init_scheduler()
{
    init_queue(task_queue, 32);

    dump_queue(task_queue);
    //other staff
}

注意有两个dump_queue,一个是init_queue(),另一个是init_queue之后。由于task_queue是malloced,我希望dump_queue的两次调用应该给出相同的结果。但第二个实际上报告了一个SIG_FAULT。

在我检查之后,在dump_queue的第二次调用中,task_queue实际上是NULL。那是为什么?

4 个答案:

答案 0 :(得分:5)

为什么不呢?您正在init_queue()函数本地范围中分配内存。

返回指针的范围有效,但赋值无效。

q = malloc(sizeof(queue));

q不会在init_queue()函数之外保留它的值。

如果queue * task_queue;是全局的,是否真的需要将其作为函数参数传递?

另外,请注意do not cast malloc()的返回值。


编辑:

不,auto-free()中没有c概念。如果不是free() - d,应用程序会明确地导致内存泄漏

答案 1 :(得分:2)

您永远不会向task_queue分配任何内容。请注意,您已按值而不是引用将task_queue传递给init_queue。您应该修改init_queue以返回queue *,或者修改其第一个参数以获取queue **并从&task_queue传递init_scheduler

也许是最简单的解决方案,因为它是全球性的,只需在task_queue = q;结束时init_queue

答案 2 :(得分:1)

它应该是init_queue(&amp; task_queue);或task_queue = init_queue();

答案 3 :(得分:0)

如果你只使用这个函数来初始化task_queue你应该这样做

void init_global_queue(int max_size)
{
    queue *task_queue = malloc(sizeof(queue));
    task_queue->size = 0;
    task_queue->max_size = max_size;
    task_queue->eles = malloc(max_size * sizeof(short));
    int i;
    for(i = 0; i < max_size; i++)
        task_queue->eles[i] = -1;
}

但不幸的是,这不是一个好的模式,因为你不能多次使用这个功能

我认为最好的方法就是这样

queue *init_queue(int max_size)
{
    queue *q = malloc(sizeof(queue));
    q->size = 0;
    q->max_size = max_size;
    q->eles = malloc(max_size * sizeof(short));
    int i;
    for(i = 0; i < max_size; i++)
        q->eles[i] = -1;
    return q;
}

当你想要初始化任何队列时,你只需要调用这个函数

queue * task_queue;
void init_scheduler()
{
    task_queue = init_queue(32);

    dump_queue(task_queue);
}

还有两件事:

使用malloc调用的返回值并不是很糟糕,事实上无论是显式还是隐式地进行了它的转换

- 执行malloc和(对于此示例)返回其值的最佳方法是这样的:

type *my_pointer = NULL;
my_pointer = malloc(sizeof (type))
if (my_pointer == NULL)
    return NULL;
my_pointer->foo = 0;
my_pointer->bar = NULL;
...
return my_pointer

因此,如果malloc无法正常工作(例如:如果你的RAM已满,malloc将返回NULL(并将errno设置为ENOMEM)),你可以正确退出程序

如果您喜欢极简主义编程,您可以这样做;)

type *my_pointer = NULL;
if (!(my_pointer = malloc(sizeof (type))))
    return NULL;

更多?男子malloc,男子错误