Deleting pointers in destructor












0















I have some pointers that I allocate in the constructor of a class and then attempt to delete in its destructor:



TileMap::TileMap(int x, int y) {

mapSize.x = x;
mapSize.y = y;

p_p_map = new Tile*[x];

for(int i = 0; i < x; i++) {

p_p_map[i] = new Tile[y];

}

randomize();

}

TileMap::~TileMap() {

for(int i = 0; i < mapSize.x; i++) {

delete p_p_map[i];

}

delete p_p_map;

}

void TileMap::randomize() {

for(int i = 0; i < mapSize.x; i++) {

for(int j = 0; j < mapSize.y; j++) {

p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());

}

}

}


At the end of the program the destructor is called to free the memory of the pointers I allocated, but when it reaches "delete p_p_map[i];" in the destructor, XCode informs me that the pointer was not allocated. I am new to C++, but I feel that I pretty explicitly allocated memory to the pointers in the randomize() function.



What error am I making?










share|improve this question


















  • 2





    You'll benefit greatly from using std::vector and either std::unique_ptr / boost::unique_ptr or std::shared_ptr / boost::shared_ptr instead of managing the memory yourself.

    – Captain Obvlious
    Nov 3 '14 at 14:39













  • It sounds like you're not following the Rule of Three, which is easy to break if you insist on managing dynamic objects by masochistically juggling raw pointers. Use std::vector.

    – Mike Seymour
    Nov 3 '14 at 14:46
















0















I have some pointers that I allocate in the constructor of a class and then attempt to delete in its destructor:



TileMap::TileMap(int x, int y) {

mapSize.x = x;
mapSize.y = y;

p_p_map = new Tile*[x];

for(int i = 0; i < x; i++) {

p_p_map[i] = new Tile[y];

}

randomize();

}

TileMap::~TileMap() {

for(int i = 0; i < mapSize.x; i++) {

delete p_p_map[i];

}

delete p_p_map;

}

void TileMap::randomize() {

for(int i = 0; i < mapSize.x; i++) {

for(int j = 0; j < mapSize.y; j++) {

p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());

}

}

}


At the end of the program the destructor is called to free the memory of the pointers I allocated, but when it reaches "delete p_p_map[i];" in the destructor, XCode informs me that the pointer was not allocated. I am new to C++, but I feel that I pretty explicitly allocated memory to the pointers in the randomize() function.



What error am I making?










share|improve this question


















  • 2





    You'll benefit greatly from using std::vector and either std::unique_ptr / boost::unique_ptr or std::shared_ptr / boost::shared_ptr instead of managing the memory yourself.

    – Captain Obvlious
    Nov 3 '14 at 14:39













  • It sounds like you're not following the Rule of Three, which is easy to break if you insist on managing dynamic objects by masochistically juggling raw pointers. Use std::vector.

    – Mike Seymour
    Nov 3 '14 at 14:46














0












0








0








I have some pointers that I allocate in the constructor of a class and then attempt to delete in its destructor:



TileMap::TileMap(int x, int y) {

mapSize.x = x;
mapSize.y = y;

p_p_map = new Tile*[x];

for(int i = 0; i < x; i++) {

p_p_map[i] = new Tile[y];

}

randomize();

}

TileMap::~TileMap() {

for(int i = 0; i < mapSize.x; i++) {

delete p_p_map[i];

}

delete p_p_map;

}

void TileMap::randomize() {

for(int i = 0; i < mapSize.x; i++) {

for(int j = 0; j < mapSize.y; j++) {

p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());

}

}

}


At the end of the program the destructor is called to free the memory of the pointers I allocated, but when it reaches "delete p_p_map[i];" in the destructor, XCode informs me that the pointer was not allocated. I am new to C++, but I feel that I pretty explicitly allocated memory to the pointers in the randomize() function.



What error am I making?










share|improve this question














I have some pointers that I allocate in the constructor of a class and then attempt to delete in its destructor:



TileMap::TileMap(int x, int y) {

mapSize.x = x;
mapSize.y = y;

p_p_map = new Tile*[x];

for(int i = 0; i < x; i++) {

p_p_map[i] = new Tile[y];

}

randomize();

}

TileMap::~TileMap() {

for(int i = 0; i < mapSize.x; i++) {

delete p_p_map[i];

}

delete p_p_map;

}

void TileMap::randomize() {

for(int i = 0; i < mapSize.x; i++) {

for(int j = 0; j < mapSize.y; j++) {

p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());

}

}

}


At the end of the program the destructor is called to free the memory of the pointers I allocated, but when it reaches "delete p_p_map[i];" in the destructor, XCode informs me that the pointer was not allocated. I am new to C++, but I feel that I pretty explicitly allocated memory to the pointers in the randomize() function.



What error am I making?







c++ xcode macos pointers






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 3 '14 at 14:34









Jokull ReynissonJokull Reynisson

1514




1514








  • 2





    You'll benefit greatly from using std::vector and either std::unique_ptr / boost::unique_ptr or std::shared_ptr / boost::shared_ptr instead of managing the memory yourself.

    – Captain Obvlious
    Nov 3 '14 at 14:39













  • It sounds like you're not following the Rule of Three, which is easy to break if you insist on managing dynamic objects by masochistically juggling raw pointers. Use std::vector.

    – Mike Seymour
    Nov 3 '14 at 14:46














  • 2





    You'll benefit greatly from using std::vector and either std::unique_ptr / boost::unique_ptr or std::shared_ptr / boost::shared_ptr instead of managing the memory yourself.

    – Captain Obvlious
    Nov 3 '14 at 14:39













  • It sounds like you're not following the Rule of Three, which is easy to break if you insist on managing dynamic objects by masochistically juggling raw pointers. Use std::vector.

    – Mike Seymour
    Nov 3 '14 at 14:46








2




2





You'll benefit greatly from using std::vector and either std::unique_ptr / boost::unique_ptr or std::shared_ptr / boost::shared_ptr instead of managing the memory yourself.

– Captain Obvlious
Nov 3 '14 at 14:39







You'll benefit greatly from using std::vector and either std::unique_ptr / boost::unique_ptr or std::shared_ptr / boost::shared_ptr instead of managing the memory yourself.

– Captain Obvlious
Nov 3 '14 at 14:39















It sounds like you're not following the Rule of Three, which is easy to break if you insist on managing dynamic objects by masochistically juggling raw pointers. Use std::vector.

– Mike Seymour
Nov 3 '14 at 14:46





It sounds like you're not following the Rule of Three, which is easy to break if you insist on managing dynamic objects by masochistically juggling raw pointers. Use std::vector.

– Mike Seymour
Nov 3 '14 at 14:46












2 Answers
2






active

oldest

votes


















1














You have to match delete with new and delete with new. Mixing one up with the other leads to issues. So if you do:



p_p_map = new Tile*[x];


you have to delete it like:



delete p_p_map;


and same with



delete p_p_map[i];


If you create something like:



pSomething = new Type;


then you delete it like:



delete pSomething;





share|improve this answer



















  • 1





    Also the OP's sample produces leaks in the randomize() function.

    – πάντα ῥεῖ
    Nov 3 '14 at 14:40






  • 2





    Indeed, *new is almost always a sign of a memory leak and usually should be omitted outright. Here too; use just ... = Tile( i, j, type)

    – MSalters
    Nov 3 '14 at 14:47



















1















What error am I making?




A few:



First, as @uesp pointed out, you mismatch new and delete calls



Second, you are using the "memory leak operator":



p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());


The construct new Tile(...) allocates memory. Then, this memory (not stored anywhere) is dereferenced, and the result is assigned to p_p_map[i][j].



Because the pointer is not stored anywhere, it is leaked.



Third, you are not respecting RAII. While this is not technically an error in itself, the way you write the code is unsafe, and in low memory conditions, you will get UB.



For example, here's what happens if you construct a Tile instance with large values for x and y:



TileMap::TileMap(int x, int y) { // e.g. (x = 1024 * 1024, y = 1024 * 1024 * 1024)

mapSize.x = x;
mapSize.y = y;

p_p_map = new Tile*[x]; // allocate 1049600 pointers block

for(int i = 0; i < x; i++) {

p_p_map[i] = new Tile[y]; // run out of memory (for example) half way through the loop

}

randomize();
}


Depending where your allocations fail, your constructor will not finish executing, meaning your TileMap instance is "half-constructed" (i.e. in an invalid state) and the destructor will not be called.



In this case, everything the class allocated is leaked, and (especially if you allocated a large size) your application is left in low memory conditions.



To fix this, make sure each pointer is managed by a different instance of a class (part of RAII). This ensures that if an allocation fails, the allocated resources are released before exitting the scope, as part of stack unwinding (as @CaptainObvlious said, use std::vector for the array and std::unique_ptr for each element).






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26716333%2fdeleting-pointers-in-destructor%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    You have to match delete with new and delete with new. Mixing one up with the other leads to issues. So if you do:



    p_p_map = new Tile*[x];


    you have to delete it like:



    delete p_p_map;


    and same with



    delete p_p_map[i];


    If you create something like:



    pSomething = new Type;


    then you delete it like:



    delete pSomething;





    share|improve this answer



















    • 1





      Also the OP's sample produces leaks in the randomize() function.

      – πάντα ῥεῖ
      Nov 3 '14 at 14:40






    • 2





      Indeed, *new is almost always a sign of a memory leak and usually should be omitted outright. Here too; use just ... = Tile( i, j, type)

      – MSalters
      Nov 3 '14 at 14:47
















    1














    You have to match delete with new and delete with new. Mixing one up with the other leads to issues. So if you do:



    p_p_map = new Tile*[x];


    you have to delete it like:



    delete p_p_map;


    and same with



    delete p_p_map[i];


    If you create something like:



    pSomething = new Type;


    then you delete it like:



    delete pSomething;





    share|improve this answer



















    • 1





      Also the OP's sample produces leaks in the randomize() function.

      – πάντα ῥεῖ
      Nov 3 '14 at 14:40






    • 2





      Indeed, *new is almost always a sign of a memory leak and usually should be omitted outright. Here too; use just ... = Tile( i, j, type)

      – MSalters
      Nov 3 '14 at 14:47














    1












    1








    1







    You have to match delete with new and delete with new. Mixing one up with the other leads to issues. So if you do:



    p_p_map = new Tile*[x];


    you have to delete it like:



    delete p_p_map;


    and same with



    delete p_p_map[i];


    If you create something like:



    pSomething = new Type;


    then you delete it like:



    delete pSomething;





    share|improve this answer













    You have to match delete with new and delete with new. Mixing one up with the other leads to issues. So if you do:



    p_p_map = new Tile*[x];


    you have to delete it like:



    delete p_p_map;


    and same with



    delete p_p_map[i];


    If you create something like:



    pSomething = new Type;


    then you delete it like:



    delete pSomething;






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 3 '14 at 14:38









    uespuesp

    5,8141514




    5,8141514








    • 1





      Also the OP's sample produces leaks in the randomize() function.

      – πάντα ῥεῖ
      Nov 3 '14 at 14:40






    • 2





      Indeed, *new is almost always a sign of a memory leak and usually should be omitted outright. Here too; use just ... = Tile( i, j, type)

      – MSalters
      Nov 3 '14 at 14:47














    • 1





      Also the OP's sample produces leaks in the randomize() function.

      – πάντα ῥεῖ
      Nov 3 '14 at 14:40






    • 2





      Indeed, *new is almost always a sign of a memory leak and usually should be omitted outright. Here too; use just ... = Tile( i, j, type)

      – MSalters
      Nov 3 '14 at 14:47








    1




    1





    Also the OP's sample produces leaks in the randomize() function.

    – πάντα ῥεῖ
    Nov 3 '14 at 14:40





    Also the OP's sample produces leaks in the randomize() function.

    – πάντα ῥεῖ
    Nov 3 '14 at 14:40




    2




    2





    Indeed, *new is almost always a sign of a memory leak and usually should be omitted outright. Here too; use just ... = Tile( i, j, type)

    – MSalters
    Nov 3 '14 at 14:47





    Indeed, *new is almost always a sign of a memory leak and usually should be omitted outright. Here too; use just ... = Tile( i, j, type)

    – MSalters
    Nov 3 '14 at 14:47













    1















    What error am I making?




    A few:



    First, as @uesp pointed out, you mismatch new and delete calls



    Second, you are using the "memory leak operator":



    p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());


    The construct new Tile(...) allocates memory. Then, this memory (not stored anywhere) is dereferenced, and the result is assigned to p_p_map[i][j].



    Because the pointer is not stored anywhere, it is leaked.



    Third, you are not respecting RAII. While this is not technically an error in itself, the way you write the code is unsafe, and in low memory conditions, you will get UB.



    For example, here's what happens if you construct a Tile instance with large values for x and y:



    TileMap::TileMap(int x, int y) { // e.g. (x = 1024 * 1024, y = 1024 * 1024 * 1024)

    mapSize.x = x;
    mapSize.y = y;

    p_p_map = new Tile*[x]; // allocate 1049600 pointers block

    for(int i = 0; i < x; i++) {

    p_p_map[i] = new Tile[y]; // run out of memory (for example) half way through the loop

    }

    randomize();
    }


    Depending where your allocations fail, your constructor will not finish executing, meaning your TileMap instance is "half-constructed" (i.e. in an invalid state) and the destructor will not be called.



    In this case, everything the class allocated is leaked, and (especially if you allocated a large size) your application is left in low memory conditions.



    To fix this, make sure each pointer is managed by a different instance of a class (part of RAII). This ensures that if an allocation fails, the allocated resources are released before exitting the scope, as part of stack unwinding (as @CaptainObvlious said, use std::vector for the array and std::unique_ptr for each element).






    share|improve this answer




























      1















      What error am I making?




      A few:



      First, as @uesp pointed out, you mismatch new and delete calls



      Second, you are using the "memory leak operator":



      p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());


      The construct new Tile(...) allocates memory. Then, this memory (not stored anywhere) is dereferenced, and the result is assigned to p_p_map[i][j].



      Because the pointer is not stored anywhere, it is leaked.



      Third, you are not respecting RAII. While this is not technically an error in itself, the way you write the code is unsafe, and in low memory conditions, you will get UB.



      For example, here's what happens if you construct a Tile instance with large values for x and y:



      TileMap::TileMap(int x, int y) { // e.g. (x = 1024 * 1024, y = 1024 * 1024 * 1024)

      mapSize.x = x;
      mapSize.y = y;

      p_p_map = new Tile*[x]; // allocate 1049600 pointers block

      for(int i = 0; i < x; i++) {

      p_p_map[i] = new Tile[y]; // run out of memory (for example) half way through the loop

      }

      randomize();
      }


      Depending where your allocations fail, your constructor will not finish executing, meaning your TileMap instance is "half-constructed" (i.e. in an invalid state) and the destructor will not be called.



      In this case, everything the class allocated is leaked, and (especially if you allocated a large size) your application is left in low memory conditions.



      To fix this, make sure each pointer is managed by a different instance of a class (part of RAII). This ensures that if an allocation fails, the allocated resources are released before exitting the scope, as part of stack unwinding (as @CaptainObvlious said, use std::vector for the array and std::unique_ptr for each element).






      share|improve this answer


























        1












        1








        1








        What error am I making?




        A few:



        First, as @uesp pointed out, you mismatch new and delete calls



        Second, you are using the "memory leak operator":



        p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());


        The construct new Tile(...) allocates memory. Then, this memory (not stored anywhere) is dereferenced, and the result is assigned to p_p_map[i][j].



        Because the pointer is not stored anywhere, it is leaked.



        Third, you are not respecting RAII. While this is not technically an error in itself, the way you write the code is unsafe, and in low memory conditions, you will get UB.



        For example, here's what happens if you construct a Tile instance with large values for x and y:



        TileMap::TileMap(int x, int y) { // e.g. (x = 1024 * 1024, y = 1024 * 1024 * 1024)

        mapSize.x = x;
        mapSize.y = y;

        p_p_map = new Tile*[x]; // allocate 1049600 pointers block

        for(int i = 0; i < x; i++) {

        p_p_map[i] = new Tile[y]; // run out of memory (for example) half way through the loop

        }

        randomize();
        }


        Depending where your allocations fail, your constructor will not finish executing, meaning your TileMap instance is "half-constructed" (i.e. in an invalid state) and the destructor will not be called.



        In this case, everything the class allocated is leaked, and (especially if you allocated a large size) your application is left in low memory conditions.



        To fix this, make sure each pointer is managed by a different instance of a class (part of RAII). This ensures that if an allocation fails, the allocated resources are released before exitting the scope, as part of stack unwinding (as @CaptainObvlious said, use std::vector for the array and std::unique_ptr for each element).






        share|improve this answer














        What error am I making?




        A few:



        First, as @uesp pointed out, you mismatch new and delete calls



        Second, you are using the "memory leak operator":



        p_p_map[i][j] = *new Tile(Tile::TileSize * i, Tile::TileSize * j, TileType::randomType());


        The construct new Tile(...) allocates memory. Then, this memory (not stored anywhere) is dereferenced, and the result is assigned to p_p_map[i][j].



        Because the pointer is not stored anywhere, it is leaked.



        Third, you are not respecting RAII. While this is not technically an error in itself, the way you write the code is unsafe, and in low memory conditions, you will get UB.



        For example, here's what happens if you construct a Tile instance with large values for x and y:



        TileMap::TileMap(int x, int y) { // e.g. (x = 1024 * 1024, y = 1024 * 1024 * 1024)

        mapSize.x = x;
        mapSize.y = y;

        p_p_map = new Tile*[x]; // allocate 1049600 pointers block

        for(int i = 0; i < x; i++) {

        p_p_map[i] = new Tile[y]; // run out of memory (for example) half way through the loop

        }

        randomize();
        }


        Depending where your allocations fail, your constructor will not finish executing, meaning your TileMap instance is "half-constructed" (i.e. in an invalid state) and the destructor will not be called.



        In this case, everything the class allocated is leaked, and (especially if you allocated a large size) your application is left in low memory conditions.



        To fix this, make sure each pointer is managed by a different instance of a class (part of RAII). This ensures that if an allocation fails, the allocated resources are released before exitting the scope, as part of stack unwinding (as @CaptainObvlious said, use std::vector for the array and std::unique_ptr for each element).







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 3 '14 at 14:53









        utnapistimutnapistim

        22.1k23572




        22.1k23572






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f26716333%2fdeleting-pointers-in-destructor%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            404 Error Contact Form 7 ajax form submitting

            How to know if a Active Directory user can login interactively

            TypeError: fit_transform() missing 1 required positional argument: 'X'