C语言 - Malloc无限空间?

时间:2011-10-10 08:09:36

标签: c malloc

我在学习C语言的malloc和指针时遇到了困难:

到目前为止我学到了什么:

  • 指针是内存地址指针。

  • malloc()分配内存位置并返回内存地址。

我正在尝试创建一个程序来测试malloc和指针,这就是我所拥有的:

#include<stdio.h>

main()
{
char *x;
x = malloc(sizeof(char) * 5);

strcpy(*x, "123456");
printf("%s",*x); //Prints 123456

}

我期待一个错误,因为我提供给malloc的大小是5,我把6个字符(123456)放到指针指向的内存位置。这里发生了什么?请帮帮我。

更新

在哪里学习malloc和指针?我对星号这个东西感到困惑,就像什么时候使用星号等。在我学习这个东西之前我不会休息!谢谢!

5 个答案:

答案 0 :(得分:5)

您正在调用未定义的行为,因为您正在编写(或尝试写入)超出已分配内存的范围。

其他挑剔:

  • 因为您正在使用strcpy(),所以您正在复制7个字节,而不是您在问题中声明的6个字节。
  • 您对strcpy()的调用存在缺陷 - 您正在传递char而不是指向char的指针作为第一个参数。
  • 如果您的编译器没有抱怨,那么您没有使用足够的警告选项。如果您正在使用GCC,则在编译器命令行中至少需要-Wall
  • 您需要为<stdlib.h>包含malloc(),为<string.h>添加strcpy()
  • 您还应明确指定int main()(或更好,int main(void))。
  • 就个人而言,我已经足够老了,我更喜欢在return(0);的末尾看到明确的main(),即使C99遵循C ++ 98并允许你省略它。

你可能不幸并且暂时不使用未定义的行为,但像valgrind这样的工具应该指出你的方式的错误。实际上,malloc()的许多实现分配了8个字节的倍数(有些是16个字节的倍数),并且鉴于您精心地不跨越8字节分配,您实际上可能会侥幸逃脱它。但是好的调试malloc()valgrind会指出你做错了。

请注意,由于在从free()返回之前没有main()分配的空间,因此您(在此上下文中相对无害)会泄漏它。另请注意,如果您复制的字符串较长(比如字母表),特别是如果您尝试free()分配的内存,或者在第一个字符串结束后再尝试分配其他内存块,然后你更有可能看到你的代码崩溃。

未定义的行为是无条件的。什么事情都可能发生。诊断它不需要任何系统。避免它!

答案 1 :(得分:3)

如果你调用malloc,你可以在堆上获取和寻址内存区域。 如果它返回,例如1000你的记忆会是这样的:

Adr  Value
----------
1000 1
1001 2
1002 3
1003 4
1004 5
1005 6
1006 0

调用strcpy()之后。你写了7个字符(比分配的多2个)。

x == 1000(指针地址)

* x == 1(取消引用值x指向)

编译器没有警告或错误消息,因为C没有任何范围检查。

答案 2 :(得分:2)

我的三分钱:

  1. 使用x,因为(* x)是存储在x处的值(在您的情况下是未知的) - 您正在写入未知的内存位置。它应该是:

    strcpy(x, "123456");

  2. 其次 - “123456”不是6个字节,它是7.你忘记了尾随零终结符。

  3. 您的程序包含当前代码可能有效,但无法保证。

  4. 我会做什么:

    #include<stdio.h>
    
    main()
    {
        char str[] = "123456";
        char *x;
        x = malloc(sizeof(str));
    
        strcpy(x, str);
        printf("%s",x); //Prints 123456
    
        free(x);
    }
    

答案 3 :(得分:1)

首先,您的代码存在一个问题:

x是指向您为5个字符分配空间的内存区域的指针。 * x它是第一个字符的值。 你应该使用strcpy(x,“123456”);

其次,分配5个字节后的内存可以有效,因此您不会收到错误。

答案 4 :(得分:0)

#include<stdio.h>

main()
{
char *x;
x = malloc(sizeof(char) * 5);

strcpy(x, "123456");
printf("%s",x); //Prints 123456

}

使用此...它将起作用

查看您的&amp;和我的计划

现在你在这里分配5个字节&amp;写入6个字节,因此第6个字节将存储在下一个连续的地址中。这个额外的字节可以通过内存管理分配给其他一个字节,所以任何时候额外的字节都可以被其他程序更改,因为第6个字节不是你的,因为你还没有malloc'd ...这就是为什么这是称为未定义的行为