在函数中使用malloc分配内存,分段错误

时间:2014-04-23 20:38:45

标签: c memory malloc

我正在尝试运行以下程序,其中我使用名为reserve的函数动态地将内存分配给变量。当我运行应用程序时,由于在一个单独的函数中为空指针分配内存,我得到分段错误,但是如果我想在main中分配内存,我不会得到这个错误。那么我做错了什么?

以下是代码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct{

unsigned char state;

/* socket fd of the client */
int fd;

/* File path requested by the client */
char file_path [255];

/* Current file offset */
unsigned long int offset;

} STATE;


void reserve(int length, void *context_data ,void *buffer)
{
    context_data = (char *) malloc(length);
    memcpy(context_data, buffer, length);
}

int main()
{
    STATE test;
    int length = sizeof(STATE);
    char buffer[1500];
    char *ptr = buffer;

    test.state = 10;
    strcpy(test.file_path, "Hello How are you");

    memcpy(ptr, &test, length);
    ptr += length;

    char *context_data;
    reserve(length, context_data, buffer);

    STATE *temp = (STATE *) context_data;
    printf("File Path %s\n", temp->file_path);
    printf("State %d\n", temp->state);
 }

6 个答案:

答案 0 :(得分:2)

请注意,context_data按值传递。因此,reserve中的本地副本已更改,但不是原始副本。因此,context_data中的main()未初始化。所以你得到了崩溃。

答案 1 :(得分:2)

在此代码中:

void reserve(int length, void *context_data ,void *buffer)
{
    context_data = (char *) malloc(length);
    memcpy(context_data, buffer, length);
}

context_data参数按值传递,因此context_data内的reservecontext_data外的reserve不是同一指针。因此,当您在此函数内部重新分配context_data时,context_data中的main指针不会更新,从而导致崩溃。

要解决此问题,请接收指向context_data变量的指针进行更新,如下所示:

void reserve(int length, void **context_data ,void *buffer)
{
    *context_data = malloc(length);
    memcpy(*context_data, buffer, length);
}
reserve(length, &context_data, buffer);

或者,让reserve返回更新的指针:

void* reserve(int length,void *buffer)
{
    void* context_data = (char *) malloc(length);
    memcpy(context_data, buffer, length);
    return context_data;
}
void* context_data = reserve(length, buffer);

希望这有帮助!

答案 2 :(得分:1)

问题是你的main()函数目前没有学习分配位置的方法。你将指针从main()传递给reserve(),这很好,可以让子程序修改指针指向的位置......但这不是你需要的;您需要reserve()修改指针指向的

void reserve(int length, void **context_data ,void *buffer)
{
    *context_data = malloc(length);
    memcpy(*context_data, buffer, length);
}

// in main():
char *context_data;
reserve(length, &context_data, buffer);

答案 3 :(得分:1)

在通过引用传递时,传递变量的地址。这里你的变量是一个指针,因此传递指针的地址。

称之为:

reserve(length, &context_data, buffer);

并更改功能定义:

void reserve(int length, void **p_context_data ,void *buffer)
{
*p_context_data = malloc(sizeof(char)*length);
.....

答案 4 :(得分:1)

您将char*传递给reserve(),但您应该像这样传递char**

char *context_data;
reserve(length, &context_data, buffer);

然后reserve应如下所示:

void reserve(int length, void **context_data ,void *buffer) {
  *context_data = (char *) malloc(length); 
  memcpy(*context_data, buffer, length); 
}

答案 5 :(得分:1)

函数void* context_data中的变量reserve()是一个局部变量,这意味着它与函数char* context_data中的变量main()不同。其值不会从main()传播回reserve()。您将值context_data传递给reserve()(未定义的值),然后将其用作STATE* temp,但该值仍未定义。

如果要更新main()函数的局部变量,则必须传递指向该变量的指针。在您的情况下,您必须将指针传递给指针,即您的代码应如下所示:

void reserve(int length, void **context_data, void *buffer)
{
    *context_data = (char *) malloc(length);
    memcpy(*context_data, buffer, length);
}

int main()
{
    ...

    char* context_data;
    reserve(length, &context_data, buffer);
    ...
}

或者,您也可以更改reserve()函数并使其返回指向已分配内存的指针。