C问题中的动态内存分配

时间:2011-05-13 16:33:58

标签: c

我正在努力增加对a的记忆,但realloc似乎没有做任何事情。在第4个数字程序崩溃。即使计数器增加并且应该是[计数器],似乎也将数字放入[0]。我知道我从[1]开始,因为当我完成输入时,我正在[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

编辑: 谢谢。你们所有人都给出了非常好的答案。

有没有办法找出分配了多少内存空间? 稍后在代码中我用sizeof(a)/ sizeof(float)检查该数组中元素的数量,现在我理解这是元素。幸运的是,我有一个计数器存储在一个所以我知道我有多少元素,但如果我不知道存储的信息我怎么知道?

6 个答案:

答案 0 :(得分:3)

realloc不正确。你得到机器上指针的大小,而不是到目前为止分配空间的大小。

float *a = (float *) malloc(sizeof(float));
/* .... */
a = realloc(a, (sizeof(a) + sizeof(float)));

因此,假设float *占用4个字节。您将始终分配4 + sizeof(float),最终您将走出去。您需要跟踪元素的数量,然后:

a = realloc(a, sizeof(float) * (el_no + 1));

当然,更好的形式是:

a = realloc(a, sizeof(*a) * (el_no + 1));

如果您以后决定更改a的类型,那么这样就会安全。

修改

作为旁注,为每个新元素调用realloc可能看起来很划算,但速度很慢。您应该采用一种策略,例如“当我用完空间时,我会将当前使用量加倍”或该行中的某些内容。

答案 1 :(得分:1)

无论你怎么想:

if (sizeof(a) == sizeof(float)) {
      return NULL;
}

正在做,事实并非如此。

答案 2 :(得分:1)

当你这样做时:

 float *a = (float *) malloc(sizeof(float));

 ...
 a = realloc(a, (sizeof(a) + sizeof(float)));
'sizeof(a)'总是返回4(在32位机器上,8在64位机器上)。 'sizeof()'尽管它的外观不是一个功能。它是一种类型的运算符,可以为您提供变量的大小。在这种情况下,'a'只是一个指针。 sizeof不会给你一个指向的大小。

您需要做的是保留一个长度变量,以跟踪malloc / realloc分配的块中的浮点数。

  int N_floats = 0 ;
  float *a = (float *)malloc(0) ;
  /* add a float */

  a = (float *)realloc(a, (N_floats+1)*sizeof(float)) ;
  a[N_floats] = 1.0 ;
  N_floats += 1;

答案 3 :(得分:0)

a = realloc(a, (sizeof(a) + sizeof(float)));

sizeof(a)sizeof(float)都是常量(大多数情况下,sizeof(anything)是常量)。所以你总是在这里要求相同数量的内存。

通常你需要的东西是

a = realloc(a, counter * sizeof(float));

  1. 你需要检查这个是否有一个错误:也许你需要(counter + 1)而不是counter,等等。
  2. 不要永远使用a = realloc(a, ...)。查看realloc如何报告错误(以及在发生错误时它对原始内存块的作用)以了解原因。
  3. 另见http://c-faq.com/malloc/realloc.html

答案 4 :(得分:0)

简而言之,sizeof(a)并不符合您的想法。 a的类型为*float,因此其大小非常小。您需要跟踪数组的长度并将其乘以sizeof(float)以获得当前大小。

答案 5 :(得分:0)

您获得的错误意味着您的堆段中存在缓冲区溢出。这是因为在第15行你做了:

a = realloc(a, (sizeof(a) + sizeof(float)));

sizeof是一个宏函数,它将在编译时阻止而不是运行时,您应该使用计数器来计算新读取所需的大小。尝试这样的事情:

a = realloc(a, (sizeof(*a) * (counter + 1))); // +  one for the counter itself

此外,您需要记住,在第21行,您将整数(计数器)转换为浮动,这将导致计数器换行并以负值重新启动。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int value = 822222233;
    float flt = value;

    printf("equal: %s\nvalue = %d\nflt = %f\n(int)flt = %d", value == flt ? "true" : "false", value, flt, ((int)flt));

    exit(0);
}

输出:

gcc -m32 -O3 -Wall -Wextra -std=c99 test.c && ./a.out
equal: true
value = 822222233
flt = 822222208.000000
(int)flt = 822222208

你可以看到你的柜台会腐败:)