简体   繁体   English

数组和malloc之间的区别

[英]Difference between array and malloc

Here is my code : 这是我的代码:

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

#define LEN 2

int main(void)
{

    char num1[LEN],num2[LEN];   //works fine with
                                //char *num1= malloc(LEN), *num2= malloc(LEN);
    int number1,number2;
    int sum;

    printf("first integer to add = ");
    scanf("%s",num1);

    printf("second integer to add = ");
    scanf("%s",num2);

    //adds integers
    number1= atoi(num1);
    number2= atoi(num2);
    sum = number1 + number2;

    //prints sum
    printf("Sum of %d and %d = %d \n",number1, number2, sum);

    return 0;
}

Here is the output : 这是输出:

first integer to add = 15
second integer to add = 12
Sum of 0 and 12 = 12

Why it is taking 0 instead of first variable 15 ? 为什么它取0而不是第一个变量15

Could not understand why this is happening. 无法理解为什么会这样。

It is working fine if I am using 如果我使用它,它工作正常

char *num1= malloc(LEN), *num2= malloc(LEN);

instead of 代替

char num1[LEN],num2[LEN];

But it should work fine with this. 但它应该可以正常工作。

Edited : 编辑:

Yes, it worked for LEN 3 but why it showed this undefined behaviour . 是的,它适用于LEN 3但为什么它显示出这种未定义的行为 I mean not working with the normal arrays and working with malloc . 我的意思是不使用normal arrays并使用malloc Now I got that it should not work with malloc also. 现在我知道它也不适用于malloc But why it worked for me, please be specific so that I can debug more accurately ? 但为什么它适合我,请具体,以便我可以更准确地调试?

Is there any issue with my system or compiler or IDE ? 我的系统或编译器或IDE有什么问题吗?

Please explain a bit more as it will be helpful or provide any links to resources. 请解释一下,因为它会有所帮助或提供任何资源链接。 Because I don't want to be unlucky anymore. 因为我不想再倒霉了。

LEN is 2, which is enough to store both digits but not the required null terminating character. LEN是2,足以存储两个数字但不存储所需的空终止字符。 You are therefore overrunning the arrays (and the heap allocations, in that version of the code!) and this causes undefined behavior . 因此,您超出了数组(以及代码版本中的堆分配!),这会导致未定义的行为 The fact that one works and the other does not is simply a byproduct of how the undefined behavior plays out on your particular system; 一个工作而另一个不工作的事实只是未定义行为如何在您的特定系统上发挥作用的副产品; the malloc version could indeed crash on a different system or a different compiler. malloc版本确实可以在不同的系统或不同的编译器上崩溃。

Correct results, incorrect results, crashing, or something completely different are all possibilities when you invoke undefined behavior. 当您调用未定义的行为时,正确的结果,不正确的结果,崩溃或完全不同的东西都是可能的。

Change LEN to 3 and your example input would work fine. LEN更改为3,您的示例输入将正常工作。

I would suggest indicating the size of your buffers in your scanf() line to avoid the undefined behavior. 我建议在scanf()行中指出缓冲区的大小,以避免未定义的行为。 You may get incorrect results, but your program at least would not crash or have a security vulnerability: 您可能会得到不正确的结果,但您的程序至少不会崩溃或存在安全漏洞:

scanf("%2s", num1);

Note that the number you use there must be one less than the size of the array -- in this example it assumes an array of size 3 (so you read a maximum of 2 characters, because you need the last character for the null terminating character). 请注意,您在那里使用的数字必须小于数组的大小 - 在此示例中,它假定大小为3的数组(因此您最多读取2个字符,因为您需要空终止字符的最后一个字符)。

LEN is defined as 2. You left no room for a null terminator. LEN定义为2.您没有留下空终止符的空间。 In the array case you would overrun the array end and damage your stack. 在数组的情况下,您将超出阵列末端并损坏堆栈。 In the malloc case you would overrun your heap and potentially damage the malloc structures. malloc情况下,你会超出你的堆并可能损坏malloc结构。

Both are undefined behaviour. 两者都是未定义的行为。 You are unlucky that your code works at all: if you were "lucky", your program would decide to crash in every case just to show you that you were triggering undefined behaviour. 你不幸的是你的代码完全可以工作:如果你“幸运”,你的程序会决定在每种情况下崩溃,只是为了告诉你你正在触发未定义的行为。 Unfortunately that's not how undefined behaviour works, so as a C programmer, you just have to be defensive and avoid entering into undefined behaviour situations. 不幸的是,这不是未定义的行为是如何工作的,因此作为C程序员,您只需要保持防御并避免进入未定义的行为情况。

Why are you using strings, anyway? 无论如何,你为什么要使用字符串? Just use scanf("%d", &number1) and you can avoid all of this. 只需使用scanf("%d", &number1)就可以避免所有这些。

Your program does not "work fine" (and should not "work fine") with either explicitly declared arrays or malloc -ed arrays. 使用显式声明的数组或malloc -ed数组,您的程序“工作正常”(并且不应该“正常工作”)。 Strings like 15 and 12 require char buffers of size 3 at least. 像字符串1512需要char大小的缓冲区3至少。 You provided buffers of size 2 . 您提供了大小为2缓冲区。 Your program overruns the buffer boundary in both cases, thus causing undefined behavior. 在两种情况下,您的程序都会超出缓冲区边界,从而导致未定义的行为。 It is just that the consequences of that undefined behavior manifest themselves differently in different versions of the code. 只是这种未定义行为的后果在不同版本的代码中表现出不同。

The malloc version has a greater chance to produce illusion of "working" since sizes of dynamically allocated memory blocks are typically rounded to the nearest implementation-depended "round" boundary (like 8 or 16 bytes). malloc版本有更大的机会产生“工作”的错觉,因为动态分配的内存块的大小通常舍入到最接近的实现依赖的“round”边界(如816字节)。 That means that your malloc calls actually allocate more memory than you ask them to. 这意味着你的malloc调用实际上分配的内存比你要求的多。 This might temporarily hide the buffer overrun problems present in your code. 这可能会暂时隐藏代码中出现的缓冲区溢出问题。 This produces the illusion of your program "working fine". 这会产生你的程序“工作正常”的错觉。

Meanwhile, the version with explicit arrays uses local arrays. 同时,具有显式数组的版本使用本地数组。 Local arrays often have precise size (as declared) and also have a greater chance to end up located next to each other in memory. 本地数组通常具有精确的大小(如声明的那样),并且还有更大的机会在内存中最终彼此相邻。 This means that buffer overrun in one array can easily destroy the contents of the other array. 这意味着一个数组中的缓冲区溢出很容易破坏另一个数组的内容。 This is exactly what happened in your case. 这正是你的情况。

However, even in the malloc -based version I'd still expect a good debugging version of standard library implementation to catch the overrun problems. 但是,即使在基于malloc的版本中,我仍然期望标准库实现的良好调试版本能够捕获溢出问题。 It is quite possible that if you attempt to actually free these malloc -ed memory blocks (something you apparently didn't bother to do), free will notice the problem and tell you that heap integrity has been violated at some point after malloc . 很有可能,如果你试图实际free这些malloc -ed内存块(你显然不愿意这样做), free会注意到这个问题,并告诉你在malloc之后的某些时候违反了堆的完整性。

PS Don't use atoi to convert strings to integers. PS不要使用atoi将字符串转换为整数。 Function that converts strings to integers is called strtol . 将字符串转换为整数的函数称为strtol

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM