2014-04-17 30 views
1

这是一个读取10个整数并将它们存储在数组中的函数(returnArr)。每增加2,并返回数组的基地址。使用基址,打印数组元素(三())。通过调用getchar改变程序的行为

#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

程序具有不确定的行为:你不能返回已被局部分配的数组:你的returnArr通话后看到的是,好了,不确定

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

结果:从该函数返回的内存可用于抓取,因此可以通过任意事件来改变,例如创建一个附加函数调用。

但它实际上是打印数组元素时putchar函数调用被注释,无用值时被包括在该程序代码的getchar函数调用。

没有putchar的呼叫arr的记忆保持不受干扰,所以你会得到旧的值。当您致电putchar时,其返回地址将被放置在堆栈上,即存储arr的地点。这是未定义行为的一个普遍问题 - 您没有得到“快速失败”行为,甚至没有得到保证。 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.