如何将数据复制到malloc返回的指针?



以下是一些来自真实stackoverflow问题的片段:

  1. table *temp = malloc(sizeof(table));
    temp = cursor->next;
    
  2. char students[][50] = { "Alan", "Bob", "Charles", "James", "Peter" };
    char (*heapStudents)[50] = malloc(sizeof(students));
    heapStudents = students;
    
  3. t = (struct carinfo_t *)malloc(sizeof(struct carinfo_t));
    t = carbase;
    
  4. char *str = (char *)malloc(20 * sizeof(char));
    str = "This is a string";
    
  5. struct node_t *temps = malloc(sizeof(struct node_t *));
    temps = src;
    

正如你所看到的,有一个清晰的模式。

p = malloc(sizeof(something));
p = something_else;

有什么问题吗?安全吗?有些人评论说"这不是指针在代码中的工作方式",但是它们实际上是什么意思呢?

有什么问题吗?

是的,有。在每种情况下都存在内存泄漏。此外,其中一些代码片段可能会做错误的事情(即,除了内存泄漏之外,程序给出了错误的答案,或者只是崩溃)。

为了理解内存泄漏,让我们回顾一下c中的赋值操作。

在简单赋值(=)中,右操作数[…]]替换存储在左操作数指定对象中的值。

简单来说,左操作数忘记了它之前保存的值,开始保存其他值。

现在让我们回忆一下,指针是一个值,指向一些数据(一个对象,或一块内存)。

在这些语句中被复制和遗忘的值是什么?

p = malloc(sizeof(something));
// p stores the value returned by malloc, which is a pointer to 
// a block of memory. note that this value is the only pointer in 
// existence that points to that block of memory.
p = something_else;
// p forgets that it was storing a pointer to a block of memory 
// returned by malloc, and now stores a different pointer,
// presumably pointing to another block of memory. 
// the old pointer is now lost forever. there is no other pointer
// that points to the same block.

这就是内存泄漏的定义。

注意内存块本身不会以任何方式、形状或形式被触摸或修改。只有指针被修改。

是指针和指向数据之间的混淆导致了这个错误。似乎人们在错误的印象下进行操作,p = malloc(...)为数据分配空间,p = something_else将数据分配到刚刚分配的空间。这确实不是指针的工作方式。这两条语句都只赋值指针,不触及指向数据。

正确的做法是什么?

这取决于"this"是什么,也就是说,取决于你需要什么。没有万能的配方。在某些情况下,你只是想复制一个指针。去掉malloc行,直接使用第二个赋值:

p = something_else; // no malloc here, just pointer assignment

在其他情况下,您需要将something_else指向的数据复制到malloc返回的新内存块中,现在由p指向(与something_else本身相反,这是一个指针):

p = malloc(sizeof(*p));           // note how sizeof is used here.
copy_data (p, something_else);    // always prefer this over sizeof(some_type)
当然,在c中没有copy_data这样的东西,这是你需要自己提供的东西,或者使用标准函数之一。例如,如果您需要复制一个字符串:
p = malloc(strlen(something_else) + 1); // note no sizeof here. the size is dynamic
strcpy(p, something_else);              // also note +1 for the null terminator
// these two lines can be replaced by p = strdup(something_else);
// strdup is a function that has recently entered the C standard, but it was
// supported by all major compilers since the dawn of time

如果你需要shallow-copyastruct:

p = malloc(sizeof(*p));
memcpy(p, something_else, sizeof(*p));
// or, if both p and something_else are declared 
// as pointers to struct something
*p = *something_else;
// if the struct contains pointers, this is probably not what you want

最新更新