C语言 C - Malloc 和 memcpy(内存管理)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7698441/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C - Malloc and memcpy (memory management)
提问by PTdude
I'm a bit new to C and I'm having trouble understanding how memory works, especially in-built functions like memcpy.
我对 C 有点陌生,我无法理解内存是如何工作的,尤其是像memcpy.
Here's a structI'm using
这是struct我正在使用的
struct data_t {
int datasize;
void *data;
};
And here's an auxiliary function that I'm using it with:
这是我正在使用的辅助功能:
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;
}
Now in the mainfunction I have no problem doing this:
现在在main函数中,我这样做没有问题:
struct data_t *data = data_create(1024);
data->data="123456a";//just an example
But this throws a Seg Fault:
但这会引发段错误:
memcpy(data->data,"123456a",strlen("1234567890a")+1);
My question is why? And how do I avoid it? Please bear in mind I'm new to C so how C deals with memory is a bit new to me
我的问题是为什么?我该如何避免?请记住我是 C 的新手,所以 C 如何处理内存对我来说有点新
Thank you.
谢谢你。
Edit: It works! Thank you very much. Completly missed the data pointer. Now everything is working fine according to valgrind.
编辑:它有效!非常感谢。完全错过了数据指针。现在根据 valgrind 一切正常。
回答by phoxis
memcpy(data->data,"123456a",strlen("1234567890a")+1);
memcpy(data->data,"123456a",strlen("1234567890a")+1);
fails because data->dataa void *type points to some garbage/invalid address which is not allocated. datahas the address of the string literal which is stored in the readonly section(like in the .rodataof the executable and loaded in the memory, which is not writable. Also, if you did not assign such a string address to the pointer variable, then it would hold some invalid/garbage address value which is not allocated or initialized with some valid permitted location. So first allocate the buffer.
失败,因为data->data一个void *类型分,没有分配一些垃圾/地址无效。data具有存储在readonly 部分中的字符串文字的地址(就像在.rodata可执行文件中并加载到内存中,这是不可写的。此外,如果您没有将这样的字符串地址分配给指针变量,那么它将保存一些无效/垃圾地址值,这些值未分配或使用一些有效的允许位置进行初始化。因此首先分配缓冲区。
data->data = malloc (sizeof (char) * size);
The mallocwill return the first location address of a block of address of atleast size * sizeof (char)bytes. Now you can copy sizebytes to this memory location pointed by data->data.
在malloc返回的ATLEAST地址块的第一个位置的地址size * sizeof (char)字节。现在您可以将size字节复制到data->data.
Remember to free the allocated memory block when you have finished working with that memory bock with the free (addr)call.
当您通过free (addr)调用完成对该内存块的处理后,请记住释放分配的内存块。
I see you have tried to allocate databuffer with a very strange manner (?):
我看到你试图以data一种非常奇怪的方式分配缓冲区(?):
struct data_t *dt=malloc(sizeof(struct data_t)+size);
for which the extra allocated sizebytes along with the struct data_t. But what ever be the case, datacomponent still points to some place which cannot be changed.
Please use:
额外分配的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;
to free first do:
首先要释放:
free (dt->data);
then
然后
free (dt);
回答by megazord
Your first mistake is this:
你的第一个错误是:
struct data_t *dt=malloc(sizeof(struct data_t)+size);
This will create a chunk of memory of size struct data_t + size. I think what you expected was that your data field inside data_t could use this memory but it cannot because data does not hold an address to this memory.
这将创建一个大小为 struct data_t + size 的内存块。我认为您期望的是 data_t 中的数据字段可以使用此内存,但不能使用,因为数据不包含此内存的地址。
Your second mistake was to assume that you where copying the value of the following string into "data":
您的第二个错误是假设您将以下字符串的值复制到“数据”中:
data->data="123456a";
What in fact happened here is that there is a string in memory "123456a" that exists for the entire life of your program. When you assign "123456a" to data->data what is actually happening is that you are taking the address of this string "123456a" and putting it in data->data you are not copying the value ("123456a") but the location or address (0x23822...) of "123456a" .
实际上这里发生的是内存中存在一个字符串“123456a”,它存在于程序的整个生命周期中。当您将“123456a”分配给数据->数据时,实际发生的情况是您正在获取此字符串“123456a”的地址并将其放入数据->数据中,您不是在复制值(“123456a”)而是位置或地址 (0x23822...) 的 "123456a" 。
Your final mistake was this:
你最后的错误是这样的:
memcpy(data->data,"123456a",strlen("1234567890a")+1);
You tried to copy the value "123456a" into memory pointed to by data. What is data pointing to? It's pointing to a read only area of memory containing your previously assigned string "123456a". In other words you told your program to write to the address of "123456a".
您试图将值“123456a”复制到数据指向的内存中。数据指向什么?它指向包含您之前分配的字符串“123456a”的只读内存区域。换句话说,您告诉您的程序写入“123456a”的地址。
Here is a program what will do what you expect:
这是一个程序,可以满足您的期望:
#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;
}
回答by lostyzd
Notice void *datais a pointer, in data_create, you didn't allocate space for it, you just make it point to a string constant "1234567890a"which is read only.
注意void *data是一个指针 in data_create,你没有为它分配空间,你只是让它指向一个"1234567890a"只读的字符串常量。
In main, you create another string constant "123456a", then you make void *datapoint to the string constant, which is read only.
在 中main,您创建另一个字符串常量"123456a",然后void *data指向只读的字符串常量。
So when you call memcpyto write to memory address which is not writeable(or without initialized), you got an error.
因此,当您调用memcpy写入不可写(或未初始化)的内存地址时,您会收到错误消息。
回答by Luka Rahne
data->data is pointer. And this pointer point to nowhere. Before doing memcpy you should allocate space and make data->data to point on this space.
数据->数据是指针。而这个指针指向无处。在执行 memcpy 之前,您应该分配空间并使 data->data 指向该空间。
data->data = malloc(strlen("1234567890a")+1);
and then memcpy will not fail as long as data->data != NULL
然后只要 data->data != NULL memcpy 就不会失败
doing
正在做
data->data = "123"
data->data = "123"
is ok, because "123" is allocated at compile time, so data->data points to beginning of string "123", but calling memcpy(data->data,"123",4)will fail, because pointer to data-data is uninitialised and point to some random location in memory that can not be even read.
没问题,因为“123”是在编译时分配的,所以 data->data 指向字符串“123”的开头,但是调用memcpy(data->data,"123",4)将失败,因为指向 data-data 的指针未初始化并指向内存中的某个随机位置,可以甚至不被阅读。

