Returning a 2D array (in C # and C ++)

I am coding a function that will return a 2D array. This got me thinking about the implications of this in C # (with garbage collection) and in C ++ (without GC)

(Why in both cases you may ask: I am now writing it on a Windows platform with C #, but in a few months I will be implementing my algorithms on an embedded device using C ++)

So basically I have a 2D array table and through a function I assigned a return value to it. My question is, what happens to the original piece of memory that contains the original table?

Now to the code: In C #

    using System;

    public class Test
    {
        public static void Main()
        {
            int[,] table= new int [10,10];  //Here some memory is separated for table 
            int[,] table= createTable(10,10); //Here the return value of createTable is assigned to the original value 

//WHAT HAPPENED TO THE ORIGINAL MEMORY THAT table HAD?

            printTable(table,10,10); //disregard this. Not that important
        }

        public static int[,] createTable(int rows, int columns)
        {
            int[,] t = new int[rows,columns];
            for(int i=0;i<rows;i++)
              for(int j=0;j<columns;j++)
                 t[i,j]=(i+j);

             return t;    
        }

        public static void printTable(int[,]t, int rows, int columns)
        {
            for(int i=0;i<rows;i++)
              for(int j=0;j<columns;j++)
                Console.WriteLine(t[i,j]);

             foreach( var im in t)
               Console.WriteLine(im);
        }
    }

      

(Please don't tell me that the first new int is unnecessary, etc. This is necessary for the question, it could be replaced by calling createTable twice)

I am assuming that in C # the garbage collector will take care of this and I don't need to worry?


Now in C ++

#include <cstdio>
#include <cstdlib>


int** createTable(int rows, int columns){
    int** table = new int*[rows];
    for(int i = 0; i < rows; i++) {
        table[i] = new int[columns]; 
        for(int j = 0; j < columns; j++){ table[i][j] = (i+j); }// sample set value;    
    }
    return table;
}
void freeTable(int** table, int rows){
    if(table){
        for(int i = 0; i < rows; i++){ if(table[i]){ delete[] table[i]; } }
        delete[] table;    
    }
}
void printTable(int** table, int rows, int columns){
    for(int i = 0; i < rows; i++){
        for(int j = 0; j < columns; j++){
            printf("(%d,%d) -> %d\n", i, j, table[i][j]);
        }    
    }
}
int main(int argc, char** argv){

    int** table = createTable(5, 5);
    table = createTable(10,10);
    printTable(table, 10, 10);
    freeTable(table, 10);
    return 0;
}

      

What happened to the original memory in the table (5x5). Does this create a memory leak when a table is assigned a 10x10 table? how to avoid this?

+3


source to share


3 answers


In C #, the garbage collector will take care of memory that is no longer available.

I have compiled your C ++ program using gcc (version: (Debian 6.4.0-1) 6.4.0 20170704) on Debian Buster.

valgrind

which is a very useful tool for checking various memory problems gave me the following result with valgrind --leak-check=full ./test

:



Memcheck, a memory error detector
Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
Command: ./test

[... program output ...]

HEAP SUMMARY:
    in use at exit: 140 bytes in 6 blocks
  total heap usage: 19 allocs, 13 frees, 74,348 bytes allocated

140 (40 direct, 100 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
   at 0x4C2C97F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x10883E: createTable(int, int) (in /home/user/code/test/test)
   by 0x108A26: main (in /home/user/code/test/test)

LEAK SUMMARY:
   definitely lost: 40 bytes in 1 blocks
   indirectly lost: 100 bytes in 5 blocks
     possibly lost: 0 bytes in 0 blocks
   still reachable: 0 bytes in 0 blocks
        suppressed: 0 bytes in 0 blocks

For counts of detected and suppressed errors, rerun with: -v
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

      

As you can see, you are definitely losing memory. Call the freeTable () function first and then reassign the pointer or use smart pointers to work around this issue.

+2


source


For the C ++ part, yes, you are creating a memory leak. You have to call freeTable

:

int** table = createTable(5, 5);
freeTable(table, 5);
table = createTable(10,10);
printTable(table, 10, 10);
freeTable(table, 10);

      

Better to use a Raii object as vector<vector<int>>

(or a dedicated class Matrix

) so you don't have to worry about freeing up memory (and you can add size information to the class as well).



So it would be simple:

auto table = createTable(5, 5);
table = createTable(10,10);
printTable(table);

      

+2


source


In this line:

//WHAT HAPPENED TO THE ORIGINAL MEMORY THAT table HAD?

      

You rewrite his link. Since the source table is no longer listed, garbage collection will clean up used space after it starts.

I cannot answer your question on C ++, sorry about that.

0


source







All Articles