C中的动态内存分配问题

发布于 2024-11-07 06:25:10 字数 3007 浏览 0 评论 0原文

我正在尝试增加 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

看透却不说透 2024-11-14 06:25:10

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 可能看起来很划算,但速度很慢。您应该采用诸如“当我用完空间时,我将当前使用的数量加倍”之类的策略或该行中的策略。

The realloc is incorrect. You are getting the size of a pointer on your machine, not the size of the allocated space so far.

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

So, suppose a float * occupies 4 bytes. You will always allocate 4 + sizeof(float) and eventually you'll step outside. You need to keep track of the number of elements and then:

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

Of course, a nicer form would be:

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

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.

绅士风度i 2024-11-14 06:25:10

无论你怎么想:这

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

是在做,它不是。

Whatever you think this:

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

Is doing, it isn't.

絕版丫頭 2024-11-14 06:25:10

当你这样做时:

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

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

“sizeof(a)”总是会返回 4(在 32 位机器上,在 64 位机器上返回 8)。 'sizeof()' 尽管它的外观不是一个函数。它是一个提供变量大小的运算符。在这种情况下,“a”只是一个指针。 sizeof 不会给你 a 所指向的大小。

您需要做的是保留一个长度变量,用于跟踪 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;

When you do:

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

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

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.

  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;
山川志 2024-11-14 06:25:10
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

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

sizeof(a) and sizeof(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

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

but

  1. You'll need to check this for off-by-one errors: maybe you'll want (counter + 1) instead of counter, or so.
  2. Don't ever use a = realloc(a, ...). Look up how realloc 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

ζ澈沫 2024-11-14 06:25:10

简而言之,sizeof(a) 并没有像你想象的那样做。 a 的类型是 *float,因此它的大小非常小。您需要跟踪数组的长度并将其乘以 sizeof(float) 以获得当前大小。

In short sizeof(a) doesn't do what you think it does. The type of a is *float so it has a very small size. You need to keep track of the length of the array and multiply that by sizeof(float) to get the current size.

洛阳烟雨空心柳 2024-11-14 06:25:10

您收到的错误意味着您的堆段中存在缓冲区溢出。这是因为在第 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

如您所见,您的计数器将损坏:)

The error you get means you have a buffer overflow in your heap segment. This is because at line 15 you do:

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

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:

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

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.

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

Output:

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

As you can see your counter will corrupt :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文