1

Here is simplified version of the code, I deleted everything that doesn't concern the problem.

#include <iostream>
#define N 3

int main() {

    int *input;
    int **cl;

    input = new int[N];
    cl = new int*[N];
    for(int i = 0; i < N; i++) {
        cl[i] = new int[N];
    }


    for(int i = 0; i < N; i++) {
        delete[] cl[i];
    }
    delete[] cl;
    delete[] input;

    return 0;
}

And the valgrind output:

==5782== HEAP SUMMARY:
==5782==     in use at exit: 72,704 bytes in 1 blocks
==5782==   total heap usage: 6 allocs, 5 frees, 72,776 bytes allocated
==5782== 
==5782== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
==5782==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5782==    by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==5782==    by 0x40104E9: call_init.part.0 (dl-init.c:72)
==5782==    by 0x40105FA: call_init (dl-init.c:30)
==5782==    by 0x40105FA: _dl_init (dl-init.c:120)
==5782==    by 0x4000CF9: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)
==5782== 
==5782== LEAK SUMMARY:
==5782==    definitely lost: 0 bytes in 0 blocks
==5782==    indirectly lost: 0 bytes in 0 blocks
==5782==      possibly lost: 0 bytes in 0 blocks
==5782==    still reachable: 72,704 bytes in 1 blocks
==5782==         suppressed: 0 bytes in 0 blocks
==5782== 
==5782== For counts of detected and suppressed errors, rerun with: -v
==5782== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

I just started to learn C++, maybe there is some stupid error that I cannot see.

I know I should also check for example if there was no "out of memory" error when allocating, but I ignore it so that code is more clear. I also know I could use e.g. vector and don't care for the allocation, but I'm still concerned what I do wrong.

Flexo
  • 87,323
  • 22
  • 191
  • 272
smutnyjoe
  • 303
  • 2
  • 10
  • 12
    Eventually you will learn `c++` and not have to deal with this.. – drescherjm Oct 14 '16 at 14:37
  • 7
    Looks correct but this is why manual memory management is best avoided if you can. – NathanOliver Oct 14 '16 at 14:38
  • 1
    @sashoalm new and delete typcally just wrap malloc and free. – NathanOliver Oct 14 '16 at 14:38
  • Tools like valgrind will stick you with your nose into it (like puppy education). – πάντα ῥεῖ Oct 14 '16 at 14:39
  • Can you show the valgrind report? – NathanOliver Oct 14 '16 at 14:40
  • BTW, I don't see a leak. – drescherjm Oct 14 '16 at 14:41
  • _@smutnyjoe_ Why are you doing [dynamic memory management](http://en.cppreference.com/w/cpp/memory) on your own? I don't see a need for that. – πάντα ῥεῖ Oct 14 '16 at 14:42
  • 1
    @NathanOliver Yes, but OP using them interchangeably is a bad sign. – sashoalm Oct 14 '16 at 14:44
  • std::vector is your friend. Make a vector of vectors and all your memory issues go away. – UKMonkey Oct 14 '16 at 14:46
  • @sashoalm Well if valgrind really shows mallocs and frees you can't blame him. not sure if it does though. – NathanOliver Oct 14 '16 at 14:47
  • 3
    @πάνταῥεῖ If OP wants to learn the basics of dynamic memory allocation, this is a good way to do it. In the industry, there are moments where you have to deal with older C++ code and have to know how it works. This is no place to question the intent of OP. – pandaman1234 Oct 14 '16 at 14:47
  • @πάνταῥεῖ It could be an college assignment. He isn't to blame for the fact that many professors stopped after C++98. – Adrian Jałoszewski Oct 14 '16 at 14:49
  • Run the check with `--leak-check=full --show-leak-kinds=all` and see if this post answers your question: http://stackoverflow.com/questions/30376601/valgrind-memory-still-reachable-with-trivial-program-using-iostream – Ionut Oct 14 '16 at 14:51
  • @lordjohncena _"This is no place to question the intent of OP."_ May be they just don't know better yet. I want to help them out with that. – πάντα ῥεῖ Oct 14 '16 at 14:53
  • 1
    The OP could have simply done one allocation and deallocation, and see if the ValGrind error still occurred. Then incrementally add allocations / deallocations until the error appears. Obviously divide and conquer approaches to solving issues isn't taught in schools these days. – PaulMcKenzie Oct 14 '16 at 14:53
  • 1
    @AdrianJałoszewski Yes, could be. You may read here in which cases I think such stuff is [bad assignments](http://dev-jungle.blogspot.de/2015/02/i-have-dream-im-dreaming-of-so-called-c.html). – πάντα ῥεῖ Oct 14 '16 at 14:55
  • 1
    Wait - 12 mallocs? your code has 2xn + 3 new's. That's an odd number of new's you call, and 11 would mean that n == 4 Perhaps you can post the entire valgrind output? – UKMonkey Oct 14 '16 at 15:15
  • I would be more concerned with if any blocks were lost rather than if allocs and frees are equivalent. If no blocks were leaked then you're probably fine. – Jacob McCarthy Oct 14 '16 at 15:31
  • To all: I am very sorry. I wanted to post a question too fast, and I see that I didn't explain correctly the problem or paste valgrind output. You can assume that n = 3 (That's why 12 mallocs). I know C and can do mallocs and frees manually (btw then there are no memory leaks when i do it manually). I now learn C++ and for the first time I tried to create and destruct array with "new" and "delete[]". I'll edit my question when i am back at home. For now, I can only add that valgrind said that the one block I lost was still reachable. – smutnyjoe Oct 14 '16 at 15:42
  • 1
    @smutnyjoe In C++ it is good practice to do resource management with constructors and destructors. That is exactly what I do in my answer with `std::vector`. The vector allocates memory in the constructor, that I use (there are others as well) and the destructor frees it again. It will be called at the end of the scope of the vector. – cdonat Oct 14 '16 at 19:45
  • @cdonat Thank you for your answer (and thank everyone for your comments). Vector could be useful and easier to implement, I admit. However, can you explain me why valgrind shows one less free than the number of mallocs (see my edited post) – smutnyjoe Oct 14 '16 at 20:53

2 Answers2

1

C++ provides you with tools, that encapsulate memory management for you.

#include <iostream>
#include <vector>

int main() {
    // read the size for the vectors
    int n;
    std::cin >> n >> '\n';

    // allocate vector with n elements
    auto input = std::vector<int>{n};

    // read the elements
    for(int i = 0; i < n; i++) {
        std::cin >> std::setw(1) >> input[i];
    }
    // print them
    for(const auto& d : input) {
        std::cout << d << std::endl;
    }

    // allocate the vectors and store 1 in each field.
    auto Cl = std::vector<std::vector<int>>{n, std::vector<int>{n, 1}};
    auto Cr = std::vector<std::vector<int>>{n, std::vector<int>{n, 1}};

    return 0;

    // will safely release all the memory here.
}

This looks a lot more like C++, and less like C. The vectors will handle all the memory management automatically for you.

Beware: I have not tested this code, so it will probably contain some bugs. I assume C++11 syntax, but it should be easy to change the code to older C++ syntax as well.

cdonat
  • 2,748
  • 16
  • 24
1

Now that you've added the valgrind output it's clearly the same issue as the one that has an answer here: Valgrind: Memory still reachable with trivial program using <iostream>

The short story is that it's not your code that causes that report. You can remove everything from main() and just return and valgrind will still give you that leak.

Read the accepted answer on that question for the explanation.

Community
  • 1
  • 1
Ionut
  • 6,436
  • 1
  • 17
  • 17