Deleting pointers in destructor
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
add a comment |
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
2
You'll benefit greatly from usingstd::vector
and eitherstd::unique_ptr
/boost::unique_ptr
orstd::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. Usestd::vector
.
– Mike Seymour
Nov 3 '14 at 14:46
add a comment |
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
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
c++ xcode macos pointers
asked Nov 3 '14 at 14:34
Jokull ReynissonJokull Reynisson
1514
1514
2
You'll benefit greatly from usingstd::vector
and eitherstd::unique_ptr
/boost::unique_ptr
orstd::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. Usestd::vector
.
– Mike Seymour
Nov 3 '14 at 14:46
add a comment |
2
You'll benefit greatly from usingstd::vector
and eitherstd::unique_ptr
/boost::unique_ptr
orstd::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. Usestd::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
add a comment |
2 Answers
2
active
oldest
votes
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;
1
Also the OP's sample produces leaks in therandomize()
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
add a comment |
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).
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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;
1
Also the OP's sample produces leaks in therandomize()
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
add a comment |
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;
1
Also the OP's sample produces leaks in therandomize()
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
add a comment |
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;
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;
answered Nov 3 '14 at 14:38
uespuesp
5,8141514
5,8141514
1
Also the OP's sample produces leaks in therandomize()
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
add a comment |
1
Also the OP's sample produces leaks in therandomize()
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
add a comment |
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).
add a comment |
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).
add a comment |
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).
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).
answered Nov 3 '14 at 14:53
utnapistimutnapistim
22.1k23572
22.1k23572
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
2
You'll benefit greatly from using
std::vector
and eitherstd::unique_ptr
/boost::unique_ptr
orstd::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