C - Malloc 和 memcpy(内存管理)
我对 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
但这会抛出一个段错误:
memcpy(data->data,"123456a",strlen("1234567890a")+1);
我的问题是为什么?我该如何避免呢? 请记住,我是 C 语言新手,所以 C 如何处理内存对我来说有点陌生,
谢谢。
编辑:它有效!非常感谢。完全错过了数据指针。现在根据 valgrind 的说法,一切正常。
I'm a bit new to C and I'm having trouble understanding how memory works, especially in-built functions like memcpy
.
Here's a struct
I'm using
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 main
function I have no problem doing this:
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
Thank you.
Edit: It works! Thank you very much. Completly missed the data pointer. Now everything is working fine according to valgrind.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
memcpy(data->data,"123456a",strlen("1234567890a")+1);
失败,因为
data->data
avoid *< /code> 类型指向一些未分配的垃圾/无效地址。
data
具有存储在 只读部分 中的字符串文字的地址(类似于可执行文件的.rodata
并加载到内存中) ,这是不可写的。此外,如果您没有将这样的字符串地址分配给指针变量,那么它将保存一些未使用某些有效允许的位置分配或初始化的无效/垃圾地址值。malloc
将返回第一个至少size * sizeof (char)
字节的地址块的位置地址 现在您可以将size
字节复制到data-> 指向的内存位置。数据
。当您使用
free (addr)
调用完成该内存块时,请记住释放已分配的内存块。我发现您已尝试分配
data
。 code> buffer 以一种非常奇怪的方式(?):为其分配了额外的
size
字节以及struct data_t
。但无论如何,data
组件仍然指向某个无法更改的地方。请使用:
首先释放,
然后执行:
memcpy(data->data,"123456a",strlen("1234567890a")+1);
fails because
data->data
avoid *
type points to some garbage/invalid address which is not allocated.data
has the address of the string literal which is stored in the readonly section (like in the.rodata
of 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.The
malloc
will return the first location address of a block of address of atleastsize * sizeof (char)
bytes. Now you can copysize
bytes to this memory location pointed bydata->data
.Remember to free the allocated memory block when you have finished working with that memory bock with the
free (addr)
call.I see you have tried to allocate
data
buffer with a very strange manner (?):for which the extra allocated
size
bytes along with thestruct data_t
. But what ever be the case,data
component still points to some place which cannot be changed.Please use:
to free first do:
then
您的第一个错误是:
这将创建一块大小为 struct data_t + size 的内存块。我认为您所期望的是 data_t 内的数据字段可以使用此内存,但它不能,因为 data 不保存此内存的地址。
您的第二个错误是假设您将以下字符串的值复制到“data”中:
实际上这里发生的是内存中存在一个字符串“123456a”,该字符串在程序的整个生命周期中都存在。当您将“123456a”分配给 data->data 时,实际发生的是,您正在获取该字符串“123456a”的地址并将其放入 data->data 中,您不是在复制该值(“123456a”),而是"123456a" 的位置或地址 (0x23822...) 。
您的最后一个错误是:
您尝试将值“123456a”复制到数据指向的内存中。数据指向什么?它指向包含您之前分配的字符串“123456a”的只读内存区域。换句话说,你告诉你的程序写入“123456a”的地址。
这是一个可以实现您期望的程序:
Your first mistake is this:
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.
Your second mistake was to assume that you where copying the value of the following string into "data":
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" .
Your final mistake was this:
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".
Here is a program what will do what you expect:
注意
void *data
是一个指针,在data_create
中,你没有为它分配空间,只是让它指向一个字符串常量"1234567890a"< /code> 是只读的。
在
main
中,您创建另一个字符串常量"123456a"
,然后使void *data
指向该字符串常量,该常量是只读的。因此,当您调用 memcpy 写入不可写(或未初始化)的内存地址时,您会收到错误。
Notice
void *data
is a pointer, indata_create
, you didn't allocate space for it, you just make it point to a string constant"1234567890a"
which is read only.In
main
, you create another string constant"123456a"
, then you makevoid *data
point to the string constant, which is read only.So when you call
memcpy
to write to memory address which is not writeable(or without initialized), you got an error.data->data 是指针。并且这个指针指向任何地方。在执行 memcpy 之前,您应该分配空间并使 data->data 指向该空间。
然后 memcpy 只要 data->data != NULL
执行
data->data = "123"
就不会失败,因为“123”是在编译时分配的,所以 data- >data 指向字符串“123”的开头,但是调用
memcpy(data->data,"123",4)
将失败,因为指向 data-data 的指针是未初始化并指向内存中的某个随机位置,甚至无法读取。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.
and then memcpy will not fail as long as data->data != NULL
doing
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.