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

标签 c pointers malloc free 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();
}

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

而且在我使用 free() 之后如果我尝试打印 description 的功能如果我没记错的话,我应该不会再得到任何输出,但我仍然会再次得到相同的字符串。可能知道这是如何工作的。我正在使用 Turbo C++ 编译器。

最佳答案

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();
}

如果您尝试以下示例程序,您可以了解发生了什么,该示例程序是您的修改版,而不是使用 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);
}

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

Before
  array1
  array2
  array3
description Hello there!

After
  array1
  array2 Hello there!
  array3 ere!

如果我们修改上面的程序如下:

#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);

}

然后我们得到以下输出。在这种情况下,我们很幸运,在 intmalloc() 上获得了相同的内存区域,所以当我们修改 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

资源所有权原则

此示例演示了使用 malloc()free() 时的两条规则。

使用 malloc() 分配您需要的内存量,并且永远不会超过您请求的内存量。如果您需要更多,请查看 realloc() 函数。

一旦使用 free() 释放了一个内存区域,就永远不要再使用该指针值。一旦内存区域被释放,您就不再拥有它。

当您使用 malloc() 时,您将成为内存的所有者,但仅限于您请求的内存。当您使用 free() 时,您放弃了内存的所有权,您不应再使用它,因为您不再拥有它。

关于c - malloc 如何获取比分配更多的数据字节数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42205541/

相关文章:

c - Frama-c,非确定性浮点值

c - Makefile 文件位于不同文件夹中

c - Malloc 分配方案

c - 嵌套结构分配内存

C puts() 没有换行符

c - 如何用C完成通配符功能?

c - 什么是 C 中的不透明指针?

c - 写一个函数到 malloc 双指针

c++ - *(char**) 如何理解这个构造?

c - 在 C 中将 const char 参数传递给 static char *argv[] 的语法