我认为realloc()
函数会重新分配内存并且不会对其进行更改。
在调试了我必须做的赋值之后,我意识到realloc()改变了内存中的一些元素并创建了bug。
所以我写了下面的代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *a, *p;
a = (int*)calloc(10, sizeof(int));
for (int i = 0;i < 10; i++)
a[i] = i;
for (int i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
p = realloc(a, 20);
p[10] = 10;
for (int i = 0; i < 11; i++)
printf("%d ", p[i]);
printf("\n");
for (int i = 0; i < 10; i++)
printf("%d ", a[i]);
return 0;
}
我得到了以下输出
有人可以解释为什么会发生这种情况吗?
我尝试使用malloc()
代替calloc()
,但现有数组也会发生变化。
答案 0 :(得分:2)
这是因为您重新分配较少的项目,而不是最初分配给calloc
的项目。混淆是由于calloc
和malloc
/ realloc
的签名略有不同。电话
a = calloc(10, sizeof(int));
在sizeof(int)
等于4的系统上分配10个sizeof(int)
块或40个字节,而
p = realloc(a, 20);
要求将该块的大小减小到20个字节。换句话说,calloc
会为您增加sizeof
,而realloc
和malloc
则需要您自己进行乘法。
一旦你告诉realloc
你只想要20个字节,那么超过第五个整数末尾的任何访问都是未定义的行为。
如果您想将尺寸扩展到20 int
s,请乘以sizeof(int)
:
p = realloc(a, 20*sizeof(int));
答案 1 :(得分:1)
重新分配由以下任一方式完成:
a)扩展或收缩ptr指出的现有区域,如果 可能。该地区的内容保持不变 新旧尺寸。如果该区域扩大,则内容为 数组的新部分未定义。
b)分配大小为new_size字节的新内存块,进行复制 内存区域的大小等于新旧大小的较小者, 并释放旧区块。
这取决于编译器的实现和您重新分配的大小。如果新分配的大小在没有片段的情况下不会出现,那么realloc肯定会在不同的位置分配内存,这比释放已经用完的内存更有效。
答案 2 :(得分:0)
p = realloc(a, 20);
在此声明中,您将p重新分配为20/4 = 5.
访问未定义的内存会导致undefined behavior
。这意味着编译器可以以任何方式运行:程序崩溃,垃圾值,有时是正确的结果。
这就是你在第5个元素之后得到垃圾值的原因。
将其修改为:p = realloc(a, 20*sizeof(int));
答案 3 :(得分:0)
语句<% Perk.all.each do |perk| %>
<input type="checkbox", class="hidden" value="<%= perk.id %>"
name="company[perk_ids][]" id="company_perk_ids_<%= perk.id %>"/>
<label class="category-choice" for="company_perk_ids_<%= perk.id %>">
<% end %>
分配a = (int*)calloc(10, sizeof(int));
,即10x4
个字节。我们可以说从40
到0x100
位置。
0x140
接下来当你 -----------------------------------------
| | | | | | | | |
-----------------------------------------
0x100 .. 0x120 0x140
a
realloc()
a
p = realloc(a, 20);
时,20
不会添加20
个字节,它会将整个内存减少到0x100
个字节,即从0x120
到p[10] = 10;
,现在当您访问0x140
时,它正在尝试将数据放在 --------------------
| | | |
--------------------
0x100 .. 0x120
a
p
位置附近,导致未定义的行为。
man 3 realloc
来自20
的
realloc()函数改变指向的内存块的大小 至 通过ptr来调整字节大小。内容将在以下范围内保持不变 该区域的起点可达到新旧尺寸的最小值。如果 新尺寸大于旧尺寸,增加的内存不会 初始化。
如果你真的想要将现有内存扩展p = realloc(a ,20*sizeof(int));
个字节,那么就像
UUID contacId=(UUID) getArguments().getSerializable(ARG_CRIME_ID);
mContact =ContactLab.get(getActivity()).getContact(contacId)
nameTextView.setText(mContact.getName());