malloc有什么优势?

时间:2013-09-09 16:13:18

标签: c++ arrays malloc dynamic-allocation variable-length-array

为某些数据分配内存有什么好处。相反,我们可以使用它们的数组。

 int *lis;
 lis = (int*) malloc ( sizeof( int ) * n );

 /* Initialize LIS values for all indexes */
 for ( i = 0; i < n; i++ )
 lis[i] = 1;

我们可以使用普通数组。

嗯,我不明白malloc是如何工作的,实际上是做什么的。所以解释它们对我来说会更有益。

假设我们在上面的代码中只用sizeof(int) * n替换n,然后尝试存储整数值,我可能面临哪些问题?有没有办法直接从内存分配空间打印存储在变量中的值,例如这里是lis

6 个答案:

答案 0 :(得分:6)

您的问题似乎是将动态分配的C风格数组与可变长度数组进行比较,这意味着这可能是您正在寻找的内容:Why aren't variable-length arrays part of the C++ standard?

然而,代码会产生最终答案: 使用std::vector对象。

只要有可能,就避免动态分配和对丑陋的内存管理负责〜&gt;尝试利用具有自动存储持续时间的对象。另一个有趣的读物可能是:Understanding the meaning of the term and the concept - RAII (Resource Acquisition is Initialization)


“并假设我们在上面的代码中只用sizeof(int) * n替换n,然后尝试存储整数值,我可能面临哪些问题?”
- 如果您仍然认为n是可以存储在此数组中的整数数量,您很可能会遇到 未定义的行为

答案 1 :(得分:3)

更基本的是,我认为,除了堆栈与堆和变量与常量问题(除了你不应该在C ++中使用malloc()这一事实之外),是一个函数退出时,本地数组不再存在。如果你返回一个指向它的指针,那么一旦调用者收到该指针就会没用,而用malloc()new动态分配的内存仍然有效。例如,您无法使用本地数组实现类似strdup()的函数,或者合理地实现链接的表示列表或树。

答案 2 :(得分:2)

答案很简单。本地 1 数组在您的堆栈上分配,这是一个为您的程序预先分配的小内存。除了几千个数据之外,你在堆栈上真的做不了多少。对于更大量的数据,您需要从堆栈中分配内存。

这是malloc的作用。

malloc分配一块与你问的一样大的内存。它返回一个指向该内存开头的指针,该指针可以被视为类似于数组。如果写入超出该内存的大小,则结果为未定义的行为。这意味着一切都可以正常工作,或者您的计算机可能会爆炸。最有可能的是,您会遇到分段错误错误。

从内存中读取值(例如用于打印)与从数组中读取相同。例如printf("%d", list[5]);

在C99之前(我知道问题标记为C ++,但可能你正在学习C-C ++编译),还有另一个原因。你无法在堆栈上拥有一个可变长度数组。 (即使是现在,堆栈上的可变长度数组也不是那么有用,因为堆栈很小)。这就是为什么对于可变数量的内存,您需要malloc函数来根据需要分配大小的内存,其大小在运行时确定。

本地数组或任何局部变量之间的另一个重要区别是对象的生命周期。一旦范围完成,局部变量就无法访问。 malloc个对象会一直存在,直到它们为free d。这在几乎所有非数组的数据结构中都是必不可少的,例如链表,二叉搜索树(和变体),(大多数)堆等。

malloc ed对象的示例是FILE。调用fopen后,保存与打开文件相关的数据的结构将使用malloc动态分配,并作为指针返回(FILE *)。


1 注意:非本地数组(全局或静态)在执行之前被分配,因此它们实际上不能在运行时确定长度。

答案 3 :(得分:1)

我假设您在询问c maloc()的目的是什么: 假设您想从用户那里获取输入,现在分配一个这样大小的数组:

int n;
scanf("%d",&n);
int arr[n];

这将失败,因为n在编译时不可用。来malloc() 你可以写:

int n;
scanf("%d",&n);
int* arr = malloc(sizeof(int)*n);

实际上malloc()在堆区域中动态分配内存

答案 4 :(得分:0)

某些较旧的编程环境根本没有提供malloc或任何等效功能。如果你需要动态内存分配,你必须在巨大的静态数组之上自己编写代码。这有几个缺点:

  • 静态数组大小对程序可以在任何时间处理多少数据设置了硬性上限,而不进行重新编译。如果您曾经尝试过在TeX中做一些复杂的事情并得到“容量超出,抱歉”的消息,这就是原因。
  • 操作系统(例如它)必须同时为静态数组保留空间,无论是否全部使用。这种现象导致“过度使用”,其中操作系统假装分配了您可能想要的所有内存,但如果您实际尝试使用的内存超过可用内容,则会终止您的进程。为什么有人想要那个?然而,在90年代中期的商业Unix中,它被大肆宣传为功能,因为它意味着潜在的巨型FORTRAN模拟需要的内存远远超过你的小太阳工作站所拥有的内存,可以在小实例大小上进行测试,没有任何问题。 (据推测,你会在一个实际上有足够内存来应对的Cray上运行 big 实例。)
  • 动态内存分配器很难实现。看看jemalloc paper,看看它有多毛。 (如果你想要自动垃圾收集it gets even more complicated。)这就是你希望大师为了每个人的利益而编码一次的事情。

所以现在即使是非常准确的嵌入式环境也会为您提供某种动态分配器。

然而, 过度使用动态内存导致效率低下,这种事实通常很难消除,因为它已经融入了体系结构中。如果看起来手头的任务不需要动态分配,也许它不会。

然而,使用动态内存分配时,你真的应该会导致它自己的问题,例如对字符串的长度施加硬性上限,或者对API进行非正规性处理(比较gethostbynamegetaddrinfo)。

所以你必须仔细考虑。

答案 5 :(得分:0)

  

我们可以使用普通数组

在C ++中(至少今年),数组具有静态大小;所以从运行时值创建一个:

int lis[n];

是不允许的。一些编译器允许将其作为非标准扩展,并且它将于明年成为标准;但是,就目前而言,如果我们想要一个动态大小的数组,我们必须动态分配它。

在C中,这意味着要弄乱malloc;但你问的是C ++,所以你想要

std::vector<int> lis(n, 1);

分配一个大小为n的数组,其中int值初始化为1。

(如果您愿意,可以使用new int[n]分配数组,并在完成时记得用delete [] lis释放它,并且如果抛出异常,请特别注意不要泄漏;但生活对于那些废话来说太短了。)

  

嗯,我不明白malloc是如何工作的,实际上是做什么的。所以解释它们对我来说会更有益。

C中的

malloc和C ++中的new从“免费商店”分配持久性内存。与变量超出范围时自动释放的局部变量的内存不同,这将持续存在,直到您明确释放它(C中的free,C ++中的delete)。如果您需要数组超过当前函数调用,则必须执行此操作。如果数组非常大,这也是一个好主意:局部变量(通常)存储在堆栈上,大小有限。如果溢出,程序将崩溃或出错。 (并且,在当前的标准C ++中,如果大小不是编译时常量,则必须这样做。)

  

假设我们在上面的代码中只用sizeof(int) * n替换n然后尝试存储整数值,我可能面临哪些问题?

您没有为n整数分配足够的空间;所以假设你的代码将尝试访问超出分配空间末尾的内存。这将导致未定义的行为;如果你很幸运会崩溃,如果你不走运就会导致数据损坏。

  

有没有办法直接从内存分配空间打印存储在变量中的值,例如这里是lis

你的意思是这样的吗?

for (i = 0; i < len; ++i) std::cout << lis[i] << '\n';