简体   繁体   中英

Difference between C and JAVA program

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.

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

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.

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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