I am coding a function that will return a 2D array. This leds me to think about the implications of this in C# (with garbage collection) and in C++(no GC)
(Why in both-you may ask: I am now writing it on a windows platform with C# but in some months I will implement my algorithms on an embedded device using C++)
So basically I have a 2D array say table, and through a function I assigned to it the return value. My question is: what happen to the original piece of memory that hold 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 not necessary, etc. It is necessary for the question, it could be replaced by calling createTable twice)
I am guessing that in C#, the garbage collector takes care of this and I don't have 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 hold by table (5x5). Does it create a memory leak when table get assigned the 10x10 table?? how do I avoid this?
In C# the garbage collector will take care of memory that isn't reachable any more.
I compiled your C++ program with gcc (Version: (Debian 6.4.0-1) 6.4.0 20170704 ) on Debian Buster.
valgrind
which is a very useful tool for checking for various kinds of memory problems, gave me the following output 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 loosing memory. Either call your freeTable() function first and then reassign your pointer or use smart pointers to get around this problem.
For C++ part, yes, you create 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 Raii object as vector<vector<int>>
(or dedicated class Matrix
) to avoid to worry about memory deallocation (and you can add size information in class too).
So it would simply be:
auto table = createTable(5, 5);
table = createTable(10,10);
printTable(table);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With