C - Malloc 和 memcpy(内存管理)

发布于 2024-12-08 23:25:59 字数 789 浏览 2 评论 0原文

我对 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

又爬满兰若 2024-12-15 23:25:59

memcpy(data->data,"123456a",strlen("1234567890a")+1);

失败,因为 data->data a void *< /code> 类型指向一些未分配的垃圾/无效地址。 data 具有存储在 只读部分 中的字符串文字的地址(类似于可执行文件的 .rodata 并加载到内存中) ,这是不可写的。此外,如果您没有将这样的字符串地址分配给指针变量,那么它将保存一些未使用某些有效允许的位置分配或初始化的无效/垃圾地址值。

data->data = malloc (sizeof (char) * size);

malloc 将返回第一个至少 size * sizeof (char) 字节的地址块的位置地址 现在您可以将 size 字节复制到 data-> 指向的内存位置。数据

当您使用free (addr)调用完成该内存块时,请记住释放已分配的内存块。


我发现您已尝试分配data。 code> buffer 以一种非常奇怪的方式(?):

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

memcpy(data->data,"123456a",strlen("1234567890a")+1);

fails because data->data a void * 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.

data->data = malloc (sizeof (char) * size);

The malloc will return the first location address of a block of address of atleast size * sizeof (char) bytes. Now you can copy size bytes to this memory location pointed by data->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 (?):

struct data_t *dt=malloc(sizeof(struct data_t)+size);

for which the extra allocated size bytes along with the struct data_t. But what ever be the case, data component still points to some place which cannot be changed.
Please use:

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);
海夕 2024-12-15 23:25:59

您的第一个错误是:

struct data_t *dt=malloc(sizeof(struct data_t)+size);

这将创建一块大小为 struct data_t + size 的内存块。我认为您所期望的是 data_t 内的数据字段可以使用此内存,但它不能,因为 data 不保存此内存的地址。

您的第二个错误是假设您将以下字符串的值复制到“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;
}

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.

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" .

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".

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;
}
辞别 2024-12-15 23:25:59

注意 void *data 是一个指针,在 data_create 中,你没有为它分配空间,只是让它指向一个字符串常量 "1234567890a"< /code> 是只读的。

main 中,您创建另一个字符串常量 "123456a",然后使 void *data 指向该字符串常量,该常量是只读的。

因此,当您调用 memcpy 写入不可写(或未初始化)的内存地址时,您会收到错误。

Notice void *data is 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.

In main, you create another string constant "123456a", then you make void *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.

心在旅行 2024-12-15 23:25:59

data->data 是指针。并且这个指针指向任何地方。在执行 memcpy 之前,您应该分配空间并使 data->data 指向该空间。

data->data = malloc(strlen("1234567890a")+1);

然后 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.

data->data = malloc(strlen("1234567890a")+1);

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文