Qno*_*ish -1 c c++ memory-management
我一直在努力寻找对以下代码中出现的错误的解释:
#include <stdlib.h>
int main() {
int m=65536;
int n=65536;
float *a;
a = (float *)malloc(m*n*sizeof(float));
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
a[i*n + j] = 0;
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么执行此程序时出现"访问冲突"错误?
内存分配是成功的,问题是在一些迭代计数的嵌套for循环中.我尝试使用较小的m&n值并且程序正常运行.
这是否意味着我内存不足?
问题是m*n*sizeof(float)
可能是溢出,导致相对较小的值.因此malloc
工作,但它没有像你期望的那样分配那么多的内存,所以你运行缓冲区的末尾.
具体来说,如果你的int
s是32位宽(这是常见的),那么65336 * 65336
已经是溢出,因为你需要至少33位来表示它.C++中的有符号整数溢出(我相信C)会导致未定义的行为,但是一个常见的结果是最重要的位被删除,而你留下较低的位.在你的情况下,它给出0.然后乘以sizeof(float)
,但零次,任何东西仍为零.
所以你试图分配0个字节.事实证明malloc会让你这样做,它会返回一个有效的指针,而不是一个空指针(如果分配失败,你会得到它).(见下面的编辑.)
所以你有一个有效的指针,但取消引用它是无效的.您完全取消引用它的这一事实是实现的副作用:为了生成一个不会被重用的唯一地址,这就是当您要求0字节时要求malloc执行的操作,malloc可能分配了一个小但非零的字节数.当您尝试引用远远超出这些范围时,通常会遇到访问冲突.
编辑:
事实证明,malloc在请求0字节时所执行的操作可能取决于您使用的是C还是C++.在过去,C标准需要一个0字节的malloc来返回一个唯一的指针作为生成"特殊"指针值的方法.在现代C++中,未定义0字节的malloc(参见C++ 11标准的3.7.4.1节中的脚注35).当我最初写答案时,我还没有意识到malloc的API已经以这种方式改变了.(我喜欢它,当一个新手问题让我学习新的东西.)VC++ 2013似乎保留了较旧的行为(返回一个唯一的指针,分配0字节),即使在编译C++时也是如此.