2014-04-17 52 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.