为什么当你输入超过malloc大小的字母时没有错误?

hl0ma9xz  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(90)
#include <stdio.h>
#include <stdlib.h>

int main() {

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

}

你好。我有个关于马洛克的问题。我只做了int大小的字节(1byte)与malloc。我输入超大的字母“苹果”(6字节),我以为输出会像“A”或“A”。但产出的却是“苹果”。这怎么可能?

m1m5dgzv

m1m5dgzv1#

内存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填充内存的分配空间。您正在删除一个包含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一步一步

仅堆栈

步骤1 main和我们变量已经加载

main
   var1
   var2
   var3

第二步我们已经输入了f1,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及其变量被卸载

main
    var1
    var2
    var3
    f2
        var5
        var6

第7步,我们离开f2,f2及其变量被卸载

main
    var1
    var2
    var3

正如你所看到的,我们在程序中进展得越多,我们在堆栈中的位置就越低。当我们碰到一个return语句时,我们回到栈中。

堆栈+堆

当你使用malloc时,内存返回的分配空间不存储在堆栈中。这允许你有一个内存段,当你离开函数时,它不会被卸载。这允许你做动态内存分配和很多其他的事情。
下面是使用malloc的一步一步的例子:
步骤1、2和3基本上与第一部分相同

main
   var1
   var2
   var3

步骤4这次我们使用malloc,从堆栈中分配一个新的内存段。其地址存储在f2_ptr中

main
    var1
    var2
    var3
    main_ptr
    f2
        var5
        var6
        f2_ptr

malloc_memory_segment

步骤5正如你所看到的,由malloc创建的内存段仍然位于内存的底部。

main
    var1
    var2
    var3
    main_ptr
    f2
        var5
        var6
        f2_ptr
        f1
            var4

malloc_memory_segment

第6步,我们离开f1,f1及其变量被卸载

main
    var1
    var2
    var3
    main_ptr
    f2
        var5
        var6
        f2_ptr

malloc_memory_segment

第7步,我们留下f2,f2和它的变量是unload,但不是malloc分配的段

main
    var1
    var2
    var3
    main_ptr

malloc_memory_segment

步骤8我们释放main_ptr,它删除malloc_memory_segment

main
    var1
    var2
    var3
    main_ptr

希望这足够清楚,它可以帮助您了解程序是如何工作的
祝你好运,继续学习

i86rm4rw

i86rm4rw2#

chr = "apple";

重写存储在chr本身中的指针。在此之后,当probram被加载时,在某处分配的字符串"apple"被使用,而不是通过malloc()分配的缓冲区。这个操作是安全的,只泄漏一小块内存。
要通过执行超出范围的写入来调用危险的 * 未定义行为 *,您可以像这样使用strcpy()

strcpy(chr, "apple");

相关问题