malloc如何获取比分配的数据更多的字节数据

Aks*_*asu 0 c malloc free pointers dynamic-memory-allocation

根据我的理解,malloc()它允许我们在运行时动态分配内存.以下是我正在研究的代码

#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main() {
  char *description;
  clrscr();
  description = malloc(2*sizeof(char));
  strcpy(description,"Hello there!");
  printf("%s",description);
  free(description);
  printf("%s",description);
  getch();
}
Run Code Online (Sandbox Code Playgroud)

我的问题是我要求系统在malloc()函数中分配2个字节的内存.因此,当我尝试填充字符串"Hello there!"并打印相同时,我应该只获得字符串的前2个字符作为输出,但我得到了我在strcpy()函数输出中给出的整个字符串.

并且在我使用free()函数后,如果我description再次尝试打印,如果我没有错,我不应该得到任何输出,但我仍然得到相同的字符串.可能知道这是如何工作的.我正在使用turbo C++编译器.

Ric*_*ers 5

malloc()函数至少分配您请求的内存量,尽管它可能更多.但是,malloc()提供的内存量并不是这里的核心问题.

C编程语言旨在提高速度和效率,这意味着许多其他语言的检查都没有完成.所以你可以写一个做错事的程序,它在某些情况下仍然可以工作,在其他情况下也不行.

在C中,指针是存储器位置的地址.C不检查地址是否是有效地址.C不会检查您尝试使用的内存量是否是正确的内存量.

所以这是一个带注释的程序版本.

#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main() {
  char *description;   // create a variable that will contain the address of a character
  clrscr();
  // allocate an array of characters. the number of characters is 2 so this
  // will allocate a minimum size memory area that will hold 2 characters.
  // malloc() may round up the size or it may not but all you can count on
  // is 2 characters in size.
  description = malloc(2*sizeof(char));
  // copy a constant string to the memory location pointed to by the variable
  // description. the strcpy() function does not check on the limits of the
  // memory. after the malloc() is done there is no size information available
  // to strcpy() or any other of the C runtime library functions in the C Standard Library
  // this is copying 11 characters plus the end of string for a total of 12 characters
  // so to be correct the memory area pointed to by description should be at least
  // 12 characters however we know from the malloc() above it is guaranteed to
  // be only 2 characters so we are going past the memory area with this strcpy().
  strcpy(description,"Hello there!");
  // however we get lucky and it works anyway.
  printf("%s",description);
  // tell the memory allocation library that you are done with the memory and it
  // can be used for something else now. the pointer will probably still be good
  // for a while because the memory allocation, which gets its memory from the
  // operating system, does not normally give any freed memory back to the OS.
  // instead it normally just keeps it until the application terminates.
  // as long as this freed memory is not used for something else, more than
  // likely whatever you put there will remain there as is. however the moment
  // the memory is given to something else, the values will change.
  free(description);
  printf("%s",description);
  getch();
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试以下示例程序(您可以对其进行修改,而不是malloc()在堆栈上使用使用变量),您可以了解发生了什么.

#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main() {
    char array1[12] = { 0 };
    char array2[2] = { 0 };
    char array3[12] = { 0 };
    char *description;
    printf("Before\n  array1 %s\n", array1);
    printf("  array2 %s\n", array2);
    printf("  array3 %s\n", array3);

    description = &array2[0];
    strcpy(description, "Hello there!");
    printf("description %s\n", description);

    printf("\nAfter\n  array1 %s\n", array1);
    printf("  array2 %s\n", array2);
    printf("  array3 %s\n", array3);
}
Run Code Online (Sandbox Code Playgroud)

使用Visual Studio 2013并在调试模式下运行时,我会收到有关在应用程序终止时覆盖内存的警告.当我进行发布构建并运行它时,没有错误,我得到以下输出.正如您所看到的,该strcpy()功能只是复制了覆盖相邻内存的字符.看起来Visual Studio 2013编译器在双字边界上对齐内存,以便只在字符串的最后几个字符在相邻的内存区域中可见.Visual Studio填充变量,array2[]以便分配的下一个变量位于双字边界上.

Before
  array1
  array2
  array3
description Hello there!

After
  array1
  array2 Hello there!
  array3 ere!
Run Code Online (Sandbox Code Playgroud)

如果我们将上述程序修改为以下内容:

#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main() {
    char array1[12] = { 0 };
    char array2[2] = { 0 };
    char array3[12] = { 0 };
    char *description;
    int  *values;
    printf("Before\n  array1 %s\n", array1);
    printf("  array2 %s\n", array2);
    printf("  array3 %s\n", array3);

    description = &array2[0];
    strcpy(description, "Hello there!");
    printf("description %s\n", description);

    printf("\nAfter\n  array1 %s\n", array1);
    printf("  array2 %s\n", array2);
    printf("  array3 %s\n", array3);

    description = malloc(8 * sizeof(char));
    strcpy(description, "this");
    printf("\n\nMalloc\n  first description %p %s\n", description, description);
    free(description);

    values = malloc(1 * sizeof(int));
    *values = 0;
    printf("  pointer %p and value %d\n", values, *values);
    printf("  second description %p %s\n", description, description);

}
Run Code Online (Sandbox Code Playgroud)

然后我们得到以下输出.在这种情况下,我们很幸运,并给予在同一存储区域malloc()int,所以当我们修改了int,我们还修改了区域指向description,因为一旦被释放,然后malloc()再用于下一次分配的区域.

Before
  array1
  array2
  array3
description Hello there!

After
  array1
  array2 Hello there!
  array3 ere!


Malloc
  first description 00944B28 this
  pointer 00944B28 and value 0
  second description 00944B28
Run Code Online (Sandbox Code Playgroud)

资源所有权原则

此示例演示了使用malloc()和时的两个规则free().

分配malloc()您需要的金额,绝不超过您请求的内存量.如果您需要更多,请查看该realloc()功能.

一旦释放内存区域,就free()再也不要使用该指针值.一旦释放,您就不再拥有内存区域.

当您使用时,您将malloc()成为内存的所有者,但只能成为您请求的内存.当你使用free()你放弃对内存的所有权,你不应该再使用它,因为你不再拥有它.