malloc 如何获取比分配更多的数据字节数
How can malloc take more number of bytes of data than assigned
根据我对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 分配 2 个字节。这意味着从起点(由 malloc 返回的起点)给我 2 个字节。
strcpy 从描述中的地址开始复制字符串 "hello there!" 中的所有字节。这不关心分配,它只是复制字节。 printf 中的 %s 告诉 printf 查找空终止字符串。
free() 用于告诉内存管理器这些字节可以再次用于其他目的。它不会删除已经存在的数据。
正如@Michael Foukarakis 指出的那样,在未分配的内存中写入字节可能会导致未定义的行为。如果在语句之间未分配的内存上写入其他内容,事情就会中断。
如果您放入更多数据,那么内存大小行为将不可预测。
没有什么会警告你你的错误行为,但内存错误随时可能发生。
description = malloc(2*sizeof(char));
您正在请求 2 个字节的存储空间。如果成功,这就是 description
将指向您可以安全使用的所有内存。
strcpy(description,"Hello there!");
您正在写入超过 malloc
分配的内存的末尾(证明:"Hello there!" 的长度超过 2),因此您的程序调用未定义的行为。
printf("%s",description);
free(description);
printf("%s",description);
上述 3 行中的 None 在调用未定义行为的程序中具有任何意义。对他们的任何期望都是毫无根据和错误的。
此外,在 free(description);
之后尝试打印 description
指向的字符串(假设是)也会调用未定义的行为。
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 和 运行ning,当应用程序终止时,我收到一条关于内存被覆盖的警告。当我进行发布构建并 运行 时,没有错误,我得到以下输出。如您所见,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);
}
然后我们得到以下输出。在这种情况下,我们很幸运,在 int
的 malloc()
上获得了相同的内存区域,所以当我们修改 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()
时,您放弃了内存的所有权,您不应该再使用它,因为您不再拥有它。
根据我对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 分配 2 个字节。这意味着从起点(由 malloc 返回的起点)给我 2 个字节。 strcpy 从描述中的地址开始复制字符串 "hello there!" 中的所有字节。这不关心分配,它只是复制字节。 printf 中的 %s 告诉 printf 查找空终止字符串。
free() 用于告诉内存管理器这些字节可以再次用于其他目的。它不会删除已经存在的数据。
正如@Michael Foukarakis 指出的那样,在未分配的内存中写入字节可能会导致未定义的行为。如果在语句之间未分配的内存上写入其他内容,事情就会中断。
如果您放入更多数据,那么内存大小行为将不可预测。
没有什么会警告你你的错误行为,但内存错误随时可能发生。
description = malloc(2*sizeof(char));
您正在请求 2 个字节的存储空间。如果成功,这就是 description
将指向您可以安全使用的所有内存。
strcpy(description,"Hello there!");
您正在写入超过 malloc
分配的内存的末尾(证明:"Hello there!" 的长度超过 2),因此您的程序调用未定义的行为。
printf("%s",description);
free(description);
printf("%s",description);
上述 3 行中的 None 在调用未定义行为的程序中具有任何意义。对他们的任何期望都是毫无根据和错误的。
此外,在 free(description);
之后尝试打印 description
指向的字符串(假设是)也会调用未定义的行为。
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 和 运行ning,当应用程序终止时,我收到一条关于内存被覆盖的警告。当我进行发布构建并 运行 时,没有错误,我得到以下输出。如您所见,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);
}
然后我们得到以下输出。在这种情况下,我们很幸运,在 int
的 malloc()
上获得了相同的内存区域,所以当我们修改 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()
时,您放弃了内存的所有权,您不应该再使用它,因为您不再拥有它。