Jump to content

std::map Memory Issue


Josh
 Share

Recommended Posts

driver->loadedassets is an std::map with the following format:

std::map<std::string,AssetBase*> loadedassets

 

This leaks memory:

   	 if (driver->loadedassets[rpath]!=NULL)
       //if (driver->loadedassets.find(fontpath)!=driver->loadedassets.end())
       {
           reference = (FontReference*)driver->loadedassets[string::Lower(rpath)];
           if (reference!=NULL)
           {
               return (Font*)(reference->Instance());
           }
       }

 

This doesn't leak memory:

   	 //if (driver->loadedassets[rpath]!=NULL)
  	 if (driver->loadedassets.find(fontpath)!=driver->loadedassets.end())
       {
           reference = (FontReference*)driver->loadedassets[string::Lower(rpath)];
           if (reference!=NULL)
           {
               return (Font*)(reference->Instance());
           }
       }

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

driver->loadedassets[rpath]

If rpath does not match the key of any element in the container, the function inserts a new element with that key and returns a reference to its mapped value. Notice that this always increases the map size by one, even if no mapped value is assigned to the element (the element is constructed using its default constructor).

 

driver->loadedassets.find( ....... )

Searches the container for an element with rpath as key and returns an iterator to it if found, otherwise it returns an iterator to map::end (the element past the end of the container).

 

 

Use find if you don't want to add something.

 

Seriosly wink.png

Roland Strålberg
Website: https://rstralberg.com

Link to comment
Share on other sites

Yeah, but if it's a pointer, it shouldn't add anything, because the default value is NULL. The problem was solved with a Clean & Rebuild. Thanks anyways for the tip.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

VS is caching a lot of things, because it's slow, so it tries to overcome the slowness with caching, which causes even more problems.

Use CodeBlocks and MinGW, and problem is solved, and you also create more cross-platform code, so less time lost on porting to iPhone and Android and Linux.

VS is the worst C++ compiler in the world, MinGW is faster by 25%, and Intel C++ is faster by 47%. Just stop using VS and you have a better life, and your customers too.

 

Same with SharePoint btw, totally horrible how slow it is because of C# garbage collection, and how you need to spam a SharePoint server every minute with a wakeup webservice. Apache does not have any of those problems, it just works.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

VS is caching a lot of things, because it's slow, so it tries to overcome the slowness with caching, which causes even more problems.

Use CodeBlocks and MinGW, and problem is solved, and you also create more cross-platform code, so less time lost on porting to iPhone and Android and Linux.

VS is the worst C++ compiler in the world, MinGW is faster by 25%, and Intel C++ is faster by 47%. Just stop using VS and you have a better life, and your customers too.

 

Same with SharePoint btw, totally horrible how slow it is because of C# garbage collection, and how you need to spam a SharePoint server every minute with a wakeup webservice. Apache does not have any of those problems, it just works.

And what has this to do with maps ???

Roland Strålberg
Website: https://rstralberg.com

Link to comment
Share on other sites

And what has this to do with maps ???

It is directly related to Josh's problem with maps, where the compiler cached things in the VS cache file and he needed to clean rebuild to make it work. For example codeblocks and mingw doesn't have such cache file, and it still compiles much faster, and creates faster exes, and the syntax highlighting works also faster and more accurate.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

for intelisence and highlighting, i am using Visual Assist X smile.png perfect tool, i can't live without it.

 

Thats so true, once you have it you won't go back.

(Win7 64bit) && (i7 3770K @ 3,5ghz) && (16gb DDR3 @ 1600mhz) && (Geforce660TI)

Link to comment
Share on other sites

***************************************

IMPORTANT

***************************************

 

It seems Roland is right. Well, sometimes. I am getting unreliable behavior when reading with the [] operator, if the key does not exist in the map. I recommend always using find() instead of the [] operator!

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

***************************************

IMPORTANT

***************************************

 

It seems Roland is right. Well, sometimes. I am getting unreliable behavior when reading with the [] operator, if the key does not exist in the map. I recommend always using find() instead of the [] operator!

 

I can only suggest to use the MSDN (msdn.microsoft.com)

 

The MSDN says under "Remarks" the following:

http://msdn.microsof...ibrary/fe72hft9

 

If the argument key value is not found, then it is inserted along with the default value of the data type.

 

operator[] may be used to insert elements into a map m using m[_Key] = DataValue; where DataValue is the value of the mapped_type of the element with a key value of _Key.

 

When using operator[] to insert elements, the returned reference does not indicate whether an insertion is changing a pre-existing element or creating a new one. The member functions find and insert can be used to determine whether an element with a specified key is already present before an insertion.

Link to comment
Share on other sites

Right but the value is a pointer, so the default value is NULL. Or it would be if STL was designed by any sane person.

mymap["whatever"]=NULL;

 

Ah well, thanks for the tips.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

The default value of an pointer is undefined (in release mode).

 

prove

 

#include <windows.h>
#include <iostream>
#include <stdio.h>
int main(int argc, char** argv)
{
int* test;
int* test2 = NULL;
std::cout << test << std::endl;
std::cout << test2 << std::endl;
system("pause");
return 0;
}

Link to comment
Share on other sites

The default value of an pointer is undefined (in release mode).

 

prove

 

#include <windows.h>
#include <iostream>
#include <stdio.h>
int main(int argc, char** argv)
{
int* test;
int* test2 = NULL;
std::cout << test << std::endl;
std::cout << test2 << std::endl;
system("pause");
return 0;
}

Exactly. In fact nothing except classes/struct's have default values in C++, and if you have no constructor which initializes the class/struct state, even they are in the dark undefined area.

Roland Strålberg
Website: https://rstralberg.com

Link to comment
Share on other sites

We can see from this program, that the [] operator will insert NULL into the map when the key is not present, at least on the MS compiler:

#include "stdafx.h"
#include <stdlib.h>
#include <list>
#include <sstream>
#include <map>
#include <iostream>

class Foo
{
public:
int i;
Foo();
};

Foo::Foo() : i(37)
{
}

int _tmain(int argc, _TCHAR* argv[])
{
std::map<std::string,Foo*> map;

Foo* foo = map["Hello"];

// (add breakpoint here)

std::cout << (foo->i) << std::endl;

return 0;
}

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Not sure what your problem is Josh, but any map query will always add the element you are asking for, unless you use find. Find will do the lookup without adding any new elements to a map. And no, STL is not stupid, it's made for maximum speed, and you have to take care of all things which are not default. That keeps the speed to it's maximum.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

It is stupid, it shouldn't add a value in when you're reading from it. They only did this because it has to return a pointer that can be gotten or set:

a = map[2]
map[2] = a

So it's a result of a limitation of the C++ language, because none of this stuff was implemented when they originally designed the thing. Which is why we call C++ an octopus made by nailing extra legs to a dog.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...