为什么输入大于 malloc size 的字符不报错?

Why is there no error when you input letters more than malloc size?

#include <stdio.h>
#include <stdlib.h>

int main() {

  char * chr = (char*)malloc(sizeof(char));
  
  chr = "apple";
  printf("%s", chr);
  
  return 0;

}

您好。 我有一个关于 malloc 的问题。 我只用 malloc 制作了 int 大小的字节(1 字节)。 然后我输入超大字母“apple”(6byte) 我认为输出会像“A”或 Null。 但输出是“苹果”。 这怎么可能?

chr = "apple";

覆盖存储在 chr 本身中的指针。之后,使用程序加载时在某处分配的字符串"apple",而不是通过malloc()分配的缓冲区。这个操作是安全的,只是泄漏了一小块内存。

要通过执行超出范围的写入来调用危险的未定义行为,您可以像这样使用strcpy()

strcpy(chr, "apple");

内存分配 my malloc 的分配方式与声明变量或数组时的内存分配方式相同。

Malloc(及其派生类)在堆中分配内存,同时在堆栈中声明字符串或 int 分配内存。

char *ptr = malloc(sizeof(char) * (elem + 1)); // Here malloc is called, memory is assined in the heap

ptr = "hello world"; // allocates a new space in the stach where the string hello world is stored 

基本上这里你没有用 apple 填充分配的 space 内存。您正在删除一个包含 apple.

的新文件

如果您是 C 编程的新手,我建议您在使用 malloc 之前学习如何使用指针和数组(尝试重现 strlen、puts 或其他类似的简单函数)

如果你想大致了解它是如何工作的,下一部分就在这里

有什么区别?

不同的是,你的堆栈内存在你的程序进程中改变 当您的主函数加载时,它会将变量加载到堆栈中。然后当你调用另一个函数如 f1 时,f1 和它的变量也将被加载到堆栈中

让我们看下面的代码:

int f1() {
    int var4 = 0;
    // step 2 and 5
    return (0);
}

char *f2() {
    int var5 = 0;
    int var6 = 0;
    char *f2_ptr = malloc(sizeof(char) * 10); // we will ignore this for the first part
    // step 4
    f1()
    // step 6
    return (ptr);
}

int main(void) {
    int var1 = 0;
    int var2 = 0;
    int var3 = 0;
    // step 1
    f1();
    // step 3
    char *main_ptr = f2()
    // step 7
    free(ptr)
    // step 8 (only for Stack + Heap part)    
    return (0);
}

一步步有你记忆中的shema

仅堆栈

step 1 main 和我们的变量已经加载

main
   var1
   var2
   var3

我们在 f1 中输入了第 2 步,main 和我们的 main 的变量仍然在这里,但现在我们还有 f1 和 f1 变量

main
    var1
    var2
    var3
    f1
        var4

第 3 步我们离开了 f1,因此它已被卸载。 main 和我们的主要变量仍在加载

main
   var1
   var2
   var3
   

第 4 步就像第 2 步一样,我们输入了一个函数 (f2),main 和我们的 main 变量仍然存在,我们加载 f2 和 f2 变量

main
    var1
    var2
    var3
    f2
        var5
        var6

第 5 步我们又一次进入了 f1。 f1 及其变量加载到堆栈底部

main
    var1
    var2
    var3
    f2
        var5
        var6
        f1
            var4

第6步我们离开f1,f1及其变量是unload

main
    var1
    var2
    var3
    f2
        var5
        var6

step 7我们离开f2,f2及其变量是unload

main
    var1
    var2
    var3

如您所见,我们在程序中取得的进展越多,我们进入的堆栈就越低。 当我们命中 return 语句时,我们回到堆栈中。

堆栈 + 堆

当您使用 malloc 时,分配的 space 内存 return 不会存储在堆栈中。这允许你有一个内存段,当你离开函数时它不会被卸载。这允许您进行动态内存分配和许多其他东西。

这是使用 malloc 的相同分步示例:

步骤一、二、三与第一部分基本相同

main
   var1
   var2
   var3
   

step 4 这次我们使用malloc,从栈中分配了一个新的内存段。它的地址存储在 f2_ptr

main
    var1
    var2
    var3
    main_ptr
    f2
        var5
        var6
        f2_ptr


malloc_memory_segment

step 5可以看到malloc创建的内存段留在内存底部

main
    var1
    var2
    var3
    main_ptr
    f2
        var5
        var6
        f2_ptr
        f1
            var4

malloc_memory_segment

第6步我们离开f1,f1及其变量是unload

main
    var1
    var2
    var3
    main_ptr
    f2
        var5
        var6
        f2_ptr


malloc_memory_segment

第7步我们离开f2,f2及其变量被卸载但不是malloc分配的段

main
    var1
    var2
    var3
    main_ptr

malloc_memory_segment

第 8 步我们释放 main_ptr 删除 malloc_memory_segment

main
    var1
    var2
    var3
    main_ptr

希望这已经够清楚了,它可以帮助您了解您的程序是如何工作的

祝你好运,继续学习