2

I have two examples of the same program. This program has a function which creates an array and returns the pointer to array.

First program (in C):

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

#define N 5

int* GetValues()
{
   int items[N] = { 1, 2, 3, 4, 5 };
   return items;
}

int main(int argc, char** argv) {

    int *array = GetValues();    
    int i;    
    for(i = 0; i < N; i++)
    {
        printf("%d\n", array[i]);
    }    

    return (EXIT_SUCCESS);
}

Second program (in Java):

package tests;

public class Tests {

    public static int[] foo() {        
        int array[] = { 1, 2, 3, 4, 5 };
        return array;        
    }

    public static void main(String[] args) {        
        int[] array = foo();        
        for(int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }                
    }
}

The result of the Java program is the following: 1, 2, 3, 4, 5

The result of the C program is the following: 1 -1075386156 -1218492432 1 -1216747208

Why do we have that different results? My version is the following.

In C program inside of the GetValues() function the items[] local array will be created and initialized. The return instraction will return the pointer to begining of the array, but this array will be allocated at the LOCAL memory of that function. When the last instruction of the GetValues() function will be invoked the local memory will be destroyed. In this case we can't predict what data are stored there and we dont know what will print the printf("%d\n", array[i]) instruction (no wonder, the memory has been destroyed and values as well).

In java program we have the following situation. Arrays in JAVA are objects. Objects in java are storing in heap. So, after executing foo() method the object array will be created and puted to the heap. After executing method local variables will be cleaned, but our pointer to array-object is still in the heap (garbage collector will understand when this object has to be deleted), what is why we are able to print it normally.

Am I right? Do I understand this features properly? If not can somebody correct me? Thanks in advance.

P.S. Sorry for my english I hope I explained my problem more or less clear.

Roman Dryndik
  • 1,167
  • 1
  • 13
  • 34
  • You are basically right. The main reason for the difference is that Java has no facility which allows you to create a reference (pointer) to a piece of automatic storage. So you cannot simply define an array in auto storage and take it's address, you're forced to create the array in heap and store only its reference in auto storage. This is a fairly severe restriction, but it neatly eliminates many possible bugs/exposures. – Hot Licks May 30 '13 at 19:22

4 Answers4

3

Yes, you are entierly correct. The array in Java is stored on the heap and is returned to the caller. The java program is just as you wrote:

int array[] = new int[5];
array[0] = 1;
...etc.
 return array;  

Which is no problem.

The array in the C program is local to the function, and the pointer to those local values are invalid when that function returrns.

nos
  • 223,662
  • 58
  • 417
  • 506
2

In the C program in int* GetValues() you are returning a pointer to a local variable which is undefined behavior, items will not exist once you return from the function. This would be once way of fixing the code:

int *items = malloc( sizeof(int) * 5 ) ;
items[0] = 1 ;
// initialize rest of array 
return items;

Just remember you need to free what you malloc.

In Java arrays are objects and objects are passed around references so the same problem does not exist in Java since Java will Garbage Collect the object once it no longer has a reference to it.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
1

In Java arrays are objects (quote from Java Language Specification):

An object is a class instance or an array.

So in the Java version of your application the array created in the foo method is actually stored on the heap, not on the stack. Therefore it can be accessed outside the foo method.

Adam Siemion
  • 15,569
  • 7
  • 58
  • 92
  • But a C array can be stored in heap as well. Being a object, per se, has nothing to do with it, other than Java does not allow "automatic" objects. It's a restriction of Java, not a "feature", that leads to the difference. – Hot Licks May 30 '13 at 19:15
  • @HotLicks Yes, sure. But this "restriction" of Java as you say leads to the difference in behavior the OP is asking about. – Adam Siemion May 30 '13 at 19:17
1

I am not sure if you are asking for help fixing the code or help understanding why there is an issue. If you want help for the latter, you seem to understand it already: since the C array is stored on the stack (what you called local function memory), the data no longer exists in memory when the function returns. Instead, you are returning a pointer to that same memory after it was freed. It's essentially the same thing as returning an uninitialized pointer, which can lead to some really nasty problems with C code!

int* GetValues()
{
    int items[N] = { 1, 2, 3, 4, 5 };
    return items;
}

If you're interested in fixing the code above, you would need to allocate space for the array on the heap before you return it. The heap has a lot more space than the stack and can be accessed from anywhere in a program so long as you have a pointer to a specific chunk.

You'd be looking at something like:

int* GetValues(){
  int * items = malloc(sizeof(item) * N)
  //I used a for loop to populate the array, just for speed
  int i;
  for(i = 0; i < 4; i++){
    items[i] = i+1
  }
  return items
}

That's probably not perfect, since I cobbled it together kind of quickly while also working on something else, but hopefully it gets the idea across. The big picture is that you need to initialize a pointer to point at a chunk in memory on the heap (done with malloc).

If the malloc code does not make sense to you, you may want to do some reading on memory management in C. It can be a pain, but it's also part of the reason why pointers can be so useful.

Magoo111
  • 113
  • 8
  • Yeah, I know how to fix to fix the code. I tried to ask if I understand the reason of this difference correct. It seems that I understand it correct. – Roman Dryndik May 30 '13 at 19:20