通过调用getchar改变程序的行为

时间:2014-04-17 16:58:14

标签: c arrays getchar

这是一个函数(returnArr),用于读取10个整数并将它们存储在数组中。将每个递增2,并返回数组基址。使用基址,打印数组元素(三())。

#include<stdio.h>
#include<stdlib.h>
int* returnArr()
{
    int arr[10];
    size_t iter = 0;
    while( iter < 10 )
    {
        scanf("%i",arr+iter);
        arr[iter]+=2;
        printf("%i ",arr[iter]);
        iter+=1;
    }
    return arr;
}

void three()
{
    size_t iter = 0;
    int* arr = returnArr();
    //putchar('\n');
    while( iter < 10 )
    {
        printf("%i ",arr[iter]);
        iter+=1;
    }
    return;
}

int main()
{
    //one();
    //two();
    three();
    return 0;
}

理想情况下,程序应该打印垃圾值,因为地址指向在数组遍历之前调用的另一个函数中的局部变量的位置。

但是当putchar函数调用被注释时它实际上是打印数组元素,当getchar函数调用包含在程序代码中时是垃圾值。

在Debian上使用gcc 4.7.2。

任何人都能解释一下吗?

-Newbie

1 个答案:

答案 0 :(得分:1)

您的程序有未定义的行为:您无法返回已在本地分配的数组:

int* returnArr()
{
    int arr[10];
    ...
    return arr; // <<== This is undefined behavior
}

returnArr调用之后看到的结果是未定义的:从函数返回的内存是up for grabs,因此它会被任意事件更改,例如进行加法函数调用。

  

但它实际上是在注释putchar函数调用时打印数组元素,当getchar函数调用包含在程序代码中时为垃圾值。

如果没有putchar的调用,arr的记忆保持不受干扰,那么你就会得到旧值。当您致电putchar时,其返回地址将被放置在堆栈上,就在存储arr的位置。这是未定义行为的一般问题 - 您没有快速失败&#34;行为,甚至是保证失败的行为。 This answer provides a very nice analogy to what's happening when you return a pointer to local from a function

要解决此问题,请动态分配数组,并在调用方中释放它,如下所示:

int *arr = malloc(10*sizeof(int)); // Instead of int arr[10];
...
int* arr = returnArr(); // Call the function
...                     // Use arr here, then...
free(arr);              // free it when you are done.