Home > Net >  C memory leak example via "new"
C memory leak example via "new"

Time:12-28

I'm in the process of learning C , and I would like to understand how new and delete work for primitive types, and if there is any automatic memory management at all when not using smart pointers.

I have written the following code that tries to trigger a memory leak by repeatedly allocating memory for 10'000 integers in the heap (that is, if I understood how new works).

#include <iostream>
#include <string>
#include <algorithm>

int* MemoryLeak(const int size) {
    std::cout << "Allocating space for " << size << " ints..." << std::endl;
    return new int[size];
}

int main() {
    std::string keepGoing = "y";
    while (keepGoing != "n") {       
        std::cout << "Leak memory? [y/n]" << std::endl; 
        
        std::cin >> keepGoing;
        std::transform(keepGoing.begin(), keepGoing.end(), keepGoing.begin(), ::tolower);
        
        if (keepGoing == "y") {
            MemoryLeak(10000);
        } else if (keepGoing != "n") {
            keepGoing = "y";
        }
    }
}

I don't have a corresponding delete call, so I would expect the memory footprint of my program to grow after each "y" I enter. However, memory footprint stays the same (according to my task manager). Why is that? And how would I have to modify my snippet in order to cause a leak?

CodePudding user response:

As noted in comments, your compiler and/or operating system may be optimizing away the problem entirely.

So let's do a few things differently:

  • Allocate bigger blocks of memory.
  • Use the return of MemoryLeak and write to it.
#include <iostream>
#include <string>
#include <algorithm>

int* MemoryLeak(const int size) {
    std::cout << "Allocating space for " << size << " ints..." << std::endl;
    return new int[size];
}

int main() {
    std::string keepGoing = "y";
    while (keepGoing != "n") {       
        std::cout << "Leak memory? [y/n]" << std::endl; 
        
        std::cin >> keepGoing;
        std::transform(keepGoing.begin(), keepGoing.end(), keepGoing.begin(), ::tolower);
        
        if (keepGoing == "y") {
            int *x = MemoryLeak(10000000);
            for (std::size_t i = 0; i < 10000000; i  ) 
                x[i] = i;
        } else if (keepGoing != "n") {
            keepGoing = "y";
        }
    }
}

If, as mentioned in comments, we use smart pointers, the memory usage of the program remains constant because when the std::unique_ptr<int[]> goes out of scope, it is destroyed and the memory deallocated.

#include <iostream>
#include <string>
#include <algorithm>
#include <memory>

std::unique_ptr<int[]> MemoryLeak(const int size) {
    std::cout << "Allocating space for " << size << " ints..." << std::endl;
    return std::make_unique<int[]>(size);
}

int main() {
    std::string keepGoing = "y";
    while (keepGoing != "n") {       
        std::cout << "Leak memory? [y/n]" << std::endl; 
        
        std::cin >> keepGoing;
        std::transform(keepGoing.begin(), keepGoing.end(), keepGoing.begin(), 
::tolower);
        
        if (keepGoing == "y") {
            auto x = MemoryLeak(10000000);
            for (std::size_t i = 0; i < 10000000; i  ) 
                x[i] = i;
        } else if (keepGoing != "n") {
            keepGoing = "y";
        }
    }
}

Of course, in practice we would likely not create a unique pointer to an array but rather achieve that effect with a std::vector.

  • Related