C中的动态内存分配问题
我正在尝试增加 a 的内存,但 realloc 似乎没有做任何事情。在第 4 个数字处程序崩溃。即使计数器增加并且应该是[计数器],数字似乎也被放入[0]中。我知道我从 a[1] 开始,因为当我完成输入时,我正在 a[0] 中写入计数器本身。
printf 的翻译:输入向量(以除点之外的任何非数字字符结束输入)。
#include <stdio.h>
#include <stdlib.h>
typedef float* vektor;
vektor beriVektor() {
int counter = 0;
float zacasna;
float *a = (float *) malloc(sizeof(float));
printf("Vpisi vektor (vpis zakljucis s katerim koli nestevilskim znakom razen pike):\n");
while(scanf("%f", &zacasna)) {
counter++;
printf("%d\n", counter);
printf("%d\n", sizeof(a));
a = realloc(a, (sizeof(a) + sizeof(float)));
a[counter] = zacasna;
}
if (sizeof(a) == sizeof(float)) {
return NULL;
}
a[0] = counter;
return a;
}
void izpisiVektor(vektor a) {
if (a == NULL) {
return;
}
else {
int velikost = sizeof(a)/sizeof(float);
for (int i = 0; i < velikost; i++) {
printf("%f", *(a+i));
}
}
}
void main(){
vektor a = beriVektor();
izpisiVektor(a);
}
输出:
ragezor@ragezor-VirtualBox:~$ ./dn09.o
Vpisi vektor (vpis zakljucis s katerim koli nestevilskim znakom razen pike):
1 2 3 4
1
4
2
4
3
4
4
4
*** glibc detected *** ./dn09.o: realloc(): invalid next size: 0x09052008 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x835501]
/lib/libc.so.6(+0x71c6d)[0x83ac6d]
/lib/libc.so.6(realloc+0xe3)[0x83af53]
./dn09.o[0x804850e]
./dn09.o[0x8048595]
/lib/libc.so.6(__libc_start_main+0xe7)[0x7dfce7]
./dn09.o[0x8048411]
======= Memory map: ========
001c9000-001e3000 r-xp 00000000 08:01 393295 /lib/libgcc_s.so.1
001e3000-001e4000 r--p 00019000 08:01 393295 /lib/libgcc_s.so.1
001e4000-001e5000 rw-p 0001a000 08:01 393295 /lib/libgcc_s.so.1
005d5000-005f1000 r-xp 00000000 08:01 393234 /lib/ld-2.12.1.so
005f1000-005f2000 r--p 0001b000 08:01 393234 /lib/ld-2.12.1.so
005f2000-005f3000 rw-p 0001c000 08:01 393234 /lib/ld-2.12.1.so
0069e000-0069f000 r-xp 00000000 00:00 0 [vdso]
007c9000-00920000 r-xp 00000000 08:01 393454 /lib/libc-2.12.1.so
00920000-00922000 r--p 00157000 08:01 393454 /lib/libc-2.12.1.so
00922000-00923000 rw-p 00159000 08:01 393454 /lib/libc-2.12.1.so
00923000-00926000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 08:01 140607 /home/ragezor/dn09.o
08049000-0804a000 r--p 00000000 08:01 140607 /home/ragezor/dn09.o
0804a000-0804b000 rw-p 00001000 08:01 140607 /home/ragezor/dn09.o
09052000-09073000 rw-p 00000000 00:00 0 [heap]
b7700000-b7721000 rw-p 00000000 00:00 0
b7721000-b7800000 ---p 00000000 00:00 0
b78d9000-b78da000 rw-p 00000000 00:00 0
b78e7000-b78eb000 rw-p 00000000 00:00 0
bfc2e000-bfc4f000 rw-p 00000000 00:00 0 [stack]
Aborted
编辑: 谢谢。你们所有人的回答都非常好。
有什么方法可以找出 vektor a 分配了多少内存空间? 稍后在代码中,我使用 sizeof(a)/sizeof(float) 检查该数组中的元素数量,现在我知道这是不正确的。幸运的是,我有计数器存储在 a 中,所以我知道我有多少元素,但如果我不存储该信息,我怎么知道?
I'm trying to increase memory of a, but realloc doesnt seem to do anything. At 4th number program crashes. It seems also that numbers are put into a[0] even though counter is increased and should be a[counter]. I know I start at a[1], because I'm writing counter itself in a[0] when I'm done inputing.
Translation of printf: Input vector (you end input with any nonnumber character except dot).
#include <stdio.h>
#include <stdlib.h>
typedef float* vektor;
vektor beriVektor() {
int counter = 0;
float zacasna;
float *a = (float *) malloc(sizeof(float));
printf("Vpisi vektor (vpis zakljucis s katerim koli nestevilskim znakom razen pike):\n");
while(scanf("%f", &zacasna)) {
counter++;
printf("%d\n", counter);
printf("%d\n", sizeof(a));
a = realloc(a, (sizeof(a) + sizeof(float)));
a[counter] = zacasna;
}
if (sizeof(a) == sizeof(float)) {
return NULL;
}
a[0] = counter;
return a;
}
void izpisiVektor(vektor a) {
if (a == NULL) {
return;
}
else {
int velikost = sizeof(a)/sizeof(float);
for (int i = 0; i < velikost; i++) {
printf("%f", *(a+i));
}
}
}
void main(){
vektor a = beriVektor();
izpisiVektor(a);
}
output:
ragezor@ragezor-VirtualBox:~$ ./dn09.o
Vpisi vektor (vpis zakljucis s katerim koli nestevilskim znakom razen pike):
1 2 3 4
1
4
2
4
3
4
4
4
*** glibc detected *** ./dn09.o: realloc(): invalid next size: 0x09052008 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x835501]
/lib/libc.so.6(+0x71c6d)[0x83ac6d]
/lib/libc.so.6(realloc+0xe3)[0x83af53]
./dn09.o[0x804850e]
./dn09.o[0x8048595]
/lib/libc.so.6(__libc_start_main+0xe7)[0x7dfce7]
./dn09.o[0x8048411]
======= Memory map: ========
001c9000-001e3000 r-xp 00000000 08:01 393295 /lib/libgcc_s.so.1
001e3000-001e4000 r--p 00019000 08:01 393295 /lib/libgcc_s.so.1
001e4000-001e5000 rw-p 0001a000 08:01 393295 /lib/libgcc_s.so.1
005d5000-005f1000 r-xp 00000000 08:01 393234 /lib/ld-2.12.1.so
005f1000-005f2000 r--p 0001b000 08:01 393234 /lib/ld-2.12.1.so
005f2000-005f3000 rw-p 0001c000 08:01 393234 /lib/ld-2.12.1.so
0069e000-0069f000 r-xp 00000000 00:00 0 [vdso]
007c9000-00920000 r-xp 00000000 08:01 393454 /lib/libc-2.12.1.so
00920000-00922000 r--p 00157000 08:01 393454 /lib/libc-2.12.1.so
00922000-00923000 rw-p 00159000 08:01 393454 /lib/libc-2.12.1.so
00923000-00926000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 08:01 140607 /home/ragezor/dn09.o
08049000-0804a000 r--p 00000000 08:01 140607 /home/ragezor/dn09.o
0804a000-0804b000 rw-p 00001000 08:01 140607 /home/ragezor/dn09.o
09052000-09073000 rw-p 00000000 00:00 0 [heap]
b7700000-b7721000 rw-p 00000000 00:00 0
b7721000-b7800000 ---p 00000000 00:00 0
b78d9000-b78da000 rw-p 00000000 00:00 0
b78e7000-b78eb000 rw-p 00000000 00:00 0
bfc2e000-bfc4f000 rw-p 00000000 00:00 0 [stack]
Aborted
edit:
Thank you. Very good answers from all of you.
Is there any way to find out how much memory space does have vektor a allocated?
Later in the code I check with sizeof(a)/sizeof(float) for number of elements in that array which now I understand is incorect. Luckily I have counter stored in a so i know how much elements i have, but if I wouldn't have that information stored how would I know?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
realloc
不正确。您获得的是机器上指针的大小,而不是到目前为止分配的空间的大小。因此,假设一个
float *
占用 4 个字节。你总是会分配4 + sizeof(float)
,最终你会走出去。您需要跟踪元素的数量,然后:当然,更好的形式是:
如果您稍后决定更改
a
的类型,这样您就可以安全了。编辑
附注,为每个新元素调用
realloc
可能看起来很划算,但速度很慢。您应该采用诸如“当我用完空间时,我将当前使用的数量加倍”之类的策略或该行中的策略。The
realloc
is incorrect. You are getting the size of a pointer on your machine, not the size of the allocated space so far.So, suppose a
float *
occupies 4 bytes. You will always allocate4 + sizeof(float)
and eventually you'll step outside. You need to keep track of the number of elements and then:Of course, a nicer form would be:
If you later decide to change the type of
a
you'll be safe this way.Edit
As a side note, calling
realloc
for each and every new element might seem like a good deal, but it's slow. You should employ a strategy like "when I run out of space I will double the current used amount" or something in that line.无论你怎么想:这
是在做,它不是。
Whatever you think this:
Is doing, it isn't.
当你这样做时:
“sizeof(a)”总是会返回 4(在 32 位机器上,在 64 位机器上返回 8)。 'sizeof()' 尽管它的外观不是一个函数。它是一个提供变量大小的运算符。在这种情况下,“a”只是一个指针。 sizeof 不会给你 a 所指向的大小。
您需要做的是保留一个长度变量,用于跟踪 malloc/realloc 分配的块中的浮点数。
When you do:
the 'sizeof(a)' is always going to return 4(on 32-bit machine, 8 on 64-bit machines). 'sizeof()' despite its appearance is NOT a function. It's an operator of sorts that gives you the size of the variable. IN this case 'a' is just a pointer. sizeof will not give you the size of what a is pointing at.
What you need to do is keep a length variable that keeps track of the number of floats you have in the block allocated by malloc/realloc.
sizeof(a)
和sizeof(float)
都是常量(在大多数情况下,sizeof(anything)
是常量)。所以你总是在这里要求相同数量的内存。通常,您需要类似的内容
,但
(counter + 1)
而不是counter
,或者这样。a = realloc(a, ...)
。查看 realloc 如何报告错误(以及发生错误时它如何处理原始内存块)以了解原因。另请参阅http://c-faq.com/malloc/realloc.html
sizeof(a)
andsizeof(float)
are both constants (for the most part,sizeof(anything)
is a constant). So you're always asking for the same amount of memory here.Typically you need something along the lines of
but
(counter + 1)
instead ofcounter
, or so.a = realloc(a, ...)
. Look up howrealloc
reports errors (and what it does with the original memory block in the event of errors) to see why.See also http://c-faq.com/malloc/realloc.html
简而言之,
sizeof(a)
并没有像你想象的那样做。a
的类型是*float
,因此它的大小非常小。您需要跟踪数组的长度并将其乘以sizeof(float)
以获得当前大小。In short
sizeof(a)
doesn't do what you think it does. The type ofa
is*float
so it has a very small size. You need to keep track of the length of the array and multiply that bysizeof(float)
to get the current size.您收到的错误意味着您的堆段中存在缓冲区溢出。这是因为在第 15 行你做了:
sizeof 是一个宏函数,它将在编译时而不是运行时起作用,你应该使用计数器来计算新读取所需的大小。尝试这样的事情:
此外,您还需要记住,在第 21 行,您将整数(计数器)转换为浮点数,这将导致计数器换行并以负值重新启动。
输出:
如您所见,您的计数器将损坏:)
The error you get means you have a buffer overflow in your heap segment. This is because at line 15 you do:
sizeof is a macro function it will be determent at compile time not a runtime you should use the counter to calculate the needed size for a new read. Try something like this:
Also you need to keep in mind that at line 21 you cast your integer (counter) to and float which will cause the counter to wrap and restart with negative value.
Output:
As you can see your counter will corrupt :)