[英]C - Malloc and memcpy (memory management)
我對C有點新,我無法理解內存是如何工作的,特別是像memcpy
這樣的內置函數。
這是我正在使用的struct
struct data_t {
int datasize;
void *data;
};
這是我正在使用的輔助功能:
struct data_t *data_create(int size)
{
struct data_t *dt=malloc(sizeof(struct data_t)+size);
dt->datasize=size;
dt->data="1234567890a";
return dt;
}
現在在main
函數中我沒有問題這樣做:
struct data_t *data = data_create(1024);
data->data="123456a";//just an example
但是這引發了一個Seg Fault:
memcpy(data->data,"123456a",strlen("1234567890a")+1);
我的問題是為什么? 我該如何避免呢? 請記住我是C的新手,所以C處理內存對我來說有點新鮮
謝謝。
編輯:它的作品! 非常感謝你。 完全錯過了數據指針。 根據valgrind的說法,現在一切正常。
memcpy(data->data,"123456a",strlen("1234567890a")+1);
失敗,因為data->data
a void *
type指向一些未分配的垃圾/無效地址。 data
具有存儲在readonly部分中的字符串文字的地址(就像在可執行文件的.rodata
中並加載到內存中,這是不可寫的。另外,如果你沒有將這樣的字符串地址分配給指針變量然后它會保存一些無效的/垃圾地址值,這些值沒有用一些有效的允許位置進行分配或初始化。所以首先分配緩沖區。
data->data = malloc (sizeof (char) * size);
malloc
將返回至少size * sizeof (char)
字節的地址塊的第一個位置地址。 現在,您可以將size
字節復制到data->data
指向的內存位置。
當你使用free (addr)
調用完成內存塊時,請記住釋放已分配的內存塊。
我看到你試圖以一種非常奇怪的方式分配data
緩沖區(?):
struct data_t *dt=malloc(sizeof(struct data_t)+size);
額外分配的size
字節以及struct data_t
。 但無論如何, data
組件仍然指向一些無法改變的地方。 請用:
struct data_t *dt = malloc(sizeof(struct data_t));
dt->data = malloc (sizeof (char) * size);
memcpy (data->data, "whatever", sizeof ("whatever")+1);
return dt;
先免費做:
free (dt->data);
然后
free (dt);
你的第一個錯誤就是:
struct data_t *dt=malloc(sizeof(struct data_t)+size);
這將創建一個大小為struct data_t + size的內存塊。 我認為你期望的是data_t中的數據字段可以使用這個內存,但它不能,因為數據不能保存這個內存的地址。
你的第二個錯誤是假設你將以下字符串的值復制到“data”中:
data->data="123456a";
實際上這里發生的是內存中有一個字符串“123456a”,它存在於程序的整個生命周期中。 當您將“123456a”分配給data-> data時,實際發生的是您正在獲取此字符串“123456a”的地址並將其放入data-> data中,您不是要復制值(“123456a”)而是位置或“123456a”的地址(0x23822 ...)。
你最后的錯誤是:
memcpy(data->data,"123456a",strlen("1234567890a")+1);
您試圖將值“123456a”復制到數據指向的內存中。 什么是指向的數據? 它指向一個包含先前分配的字符串“123456a”的只讀內存區域。 換句話說,您告訴您的程序寫入“123456a”的地址。
這是一個程序,它會做你期望的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct {
size_t datasize;
char *data;
} data_t;
data_t *data_create(size_t size)
{
data_t *dt;
dt = malloc(sizeof(data_t));
assert(dt != NULL);
dt->data = malloc(size);
assert(dt->data != NULL);
dt->datasize = size;
/* need to decide what to do when this happens */
assert((strlen("1234567890a") + 1) < size);
strcpy(dt->data, "1234567890a");
return dt;
}
void data_destroy(data_t *dt)
{
free(dt->data);
free(dt);
}
int main(void)
{
data_t *data = data_create(1024);
/* data->data="123456a"; DONT DO THIS YOU WILL CAUSE A MEMORY LEAK */
assert(data->datasize >= (strlen("123456a")+1));
memcpy(data->data, "123456a", strlen("123456a")+1);
printf("%s\n", data->data);
data_destroy(data);
return EXIT_SUCCESS;
}
注意void *data
是一個指針,在data_create
,你沒有為它分配空間,你只需要指向一個只讀的字符串常量"1234567890a"
。
在main
,您創建另一個字符串常量"123456a"
,然后將void *data
指向字符串常量,這是只讀的。
因此,當您調用memcpy
來寫入不可寫(或未初始化)的內存地址時,您會收到錯誤。
data-> data是指針。 而這個指針指向無處。 在進行memcpy之前,您應該分配空間並使data-> data指向此空間。
data->data = malloc(strlen("1234567890a")+1);
然后只要data-> data!= NULL,memcpy就不會失敗
干
data->data = "123"
沒問題,因為“123”是在編譯時分配的,所以data-> data指向字符串“123”的開頭,但調用memcpy(data->data,"123",4)
將失敗,因為指針指向數據 -數據未初始化並指向內存中無法讀取的某個隨機位置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.