2011-05-13 29 views
1

我想增加a的内存,但是realloc似乎没有做任何事情。在第四个号码程序崩溃。看起来数字也被放到了[0]中,即使计数器增加了也应该是[counter]。我知道我从[1]开始,因为当我完成输入时,我正在写一个[0]的计数器。在C问题中的动态内存分配

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); 

} 

输出:

[email protected]:~$ ./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分配? 后来在代码中,我检查了sizeof(a)/ sizeof(float)这个数组中元素的个数,现在我知道它是不正确的。幸运的是,我有柜台存储在一个所以我知道我有多少元素,但如果我不会有这些信息存储我怎么知道?

回答

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为每一个新的元素似乎是一个很好的协议,但它的速度慢。你应该采用一种策略,比如“当我用完空间时,我将把当前使用量增加一倍”,或者在这一行中。

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如何报告错误(以及在发生错误时如何处理原始内存块)以查看原因。

http://c-faq.com/malloc/realloc.html

+0

如果我理解第2点,realloc的分配更多的内存和一切都很好。但是,当它不能返回NULL指针和分配给a的内存丢失,因此创建内存泄漏? 我不确定realloc是否在其他地方找到了内存空间,所以它不仅仅添加一些空间而是重新分配它,它是否释放了这个空间,或者您必须手动执行该操作? – ragezor 2011-05-13 17:15:57

+0

(您的问题主要在书籍和文档中得到解答,C-FAQ条目也涵盖了这一点。)@ragezor:第2点是,如果内存分配失败,realloc()将单独保留原始内存块。然后,如果'a'是你唯一指向那个块的指针,那么你只是抛弃了获取它的唯一方法。因此内存泄漏。最明显的方法是将realloc()的结果放入另一个变量中,如果分配成功,则将其分配给'a'。 – 2011-05-13 17:36:04

+0

Administrivia:你已经根据DipSwitch和我的回答提出了问题,很明显你从他们那里得到了一些东西。那么,如何对我们的答案进行一点投票... – 2011-05-13 17:38:02

1

不管你认为这个:

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

是干什么的,事实并非如此。

0

总之sizeof(a)不会做你认为的事情。 a的类型是*float,所以它的尺寸非常小。您需要跟踪数组的长度并将其乘以sizeof(float)以获取当前大小。

1

这样做:

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

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

的 '的sizeof(A)' 总是要(在64位机器上32位机,8)返回4。 '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; 
0

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

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

的sizeof是微距功能将是威慑在编译时不运行时,你应该使用计数器来计算所需要的尺寸新的读取。尝试是这样的:

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

而且你需要记住,在第21行投放至整数(计数器)和浮动,这将导致计数器来包装,并用负值重启。

输出:

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

正如你可以看到你的计数器将腐败:)

+0

你能解释一下它是什么意思吗?这不影响我的程序,但我想知道任何一种方式。 – ragezor 2011-05-13 17:08:27

+0

浮游物不会存储确切的数字,但它们以科学记数法存储其中的价值,这意味着如果超出范围,浮游物可以存储,因为它是四舍五入的。请参阅编辑。也有可能超出浮动价值实际上是负值而不是正值的点。 – DipSwitch 2011-05-13 17:28:01

+0

好的,我怀疑过那样的事情。它也发生在Java中。我认为反指向本身会腐败,因为C的指针的想法和我还没有模糊的东西。我刚刚测试了这一点,只有flt是incorect和价值保持不变。 – ragezor 2011-05-13 17:41:50