簡體   English   中英

在函數中使用malloc分配內存,出現分段錯誤

[英]Allocating memory using malloc in a function, segmentation fault

我正在嘗試運行以下程序,在該程序中,我使用稱為reserve的函數將內存動態分配給變量。 當我運行應用程序時,由於在空指針的單獨函數中分配內存而導致分段錯誤,但是如果我要在主函數中分配內存,則不會出現此錯誤。 那我在做什么錯?

這是代碼:

#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);
 }

請注意, context_data是按值傳遞的。 因此, reserve的本地副本已更改,但原始副本未更改。 結果, main()context_data沒有初始化。 這樣您就崩潰了。

在此代碼中:

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時, maincontext_data指針不會更新,從而導致崩潰。

要解決此問題,可以采用指向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);

希望這可以幫助!

問題是您的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);

通過引用傳遞,您傳遞變量的地址。 這里的變量是一個指針,因此傳遞指針的地址。

像這樣稱呼它:

reserve(length, &context_data, buffer);

並更改函數定義:

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

您將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); 
}

函數reserve()中的變量void* context_data是局部變量,這意味着它與函數main()變量char* context_data不同。 它的值不會從reserve()傳播回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()函數並使它返回指向已分配內存的指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM