std::map and insert()

D

dragoncoder

Hello all,

I have the following code. Plesae have a look.

#include <iostream>
#include <string>
#include <map>
#include <cstdlib>

using namespace std;

typedef map<int,string, less<int> > INT2STRING;
INT2STRING::iterator theIterator;

int main(int argC,char ** argV)
{
INT2STRING * pmap = NULL;
pmap = new INT2STRING;
//pmap = static_cast<INT2STRING*>(malloc(sizeof(INT2STRING)));
for(int i =0;i<10;i++)
{
string buff = "Buffer";
pmap->insert(INT2STRING::value_type(i,buff));
}

for(int i=0;i<10;i++)
{
theIterator = pmap->find(i);
if(theIterator != pmap->end() ) cout << (*theIterator).second<<
"\n";
else cout << "[err] ";
}
if (pmap != NULL) delete pmap;
//if (pmap != NULL) free (pmap);
}

The code runs perfectly fine. But if I change the new call to malloc()
and delete to free(), I get a segmentation fault ( I am expecting the
problem at the call to insert() ).

Is it necessary to create the map using new only? Can someone please
quote the section of standard which does not allow this to happen.

Best regards
 
J

Jonathan Mcdougall

dragoncoder said:
Hello all,

I have the following code. Plesae have a look.

#include <iostream>
#include <string>
#include <map>
#include <cstdlib>

using namespace std;

typedef map<int,string, less<int> > INT2STRING;
INT2STRING::iterator theIterator;

int main(int argC,char ** argV)
{
INT2STRING * pmap = NULL;
pmap = new INT2STRING;
//pmap = static_cast<INT2STRING*>(malloc(sizeof(INT2STRING)));
[snip]

The code runs perfectly fine. But if I change the new call to malloc()
and delete to free(), I get a segmentation fault ( I am expecting the
problem at the call to insert() ).

malloc() doesn't call constructors and free() doesn't call destructors.
Don't use them with non POD types.


Jonathan
 
M

Mark P

dragoncoder said:
Hello all,

I have the following code. Plesae have a look.

#include <iostream>
#include <string>
#include <map>
#include <cstdlib>

using namespace std;

typedef map<int,string, less<int> > INT2STRING;
INT2STRING::iterator theIterator;

int main(int argC,char ** argV)
{
INT2STRING * pmap = NULL;
pmap = new INT2STRING;
//pmap = static_cast<INT2STRING*>(malloc(sizeof(INT2STRING)));
for(int i =0;i<10;i++)
{
string buff = "Buffer";
pmap->insert(INT2STRING::value_type(i,buff));
}

for(int i=0;i<10;i++)
{
theIterator = pmap->find(i);
if(theIterator != pmap->end() ) cout << (*theIterator).second<<
"\n";
else cout << "[err] ";
}
if (pmap != NULL) delete pmap;
//if (pmap != NULL) free (pmap);
}

The code runs perfectly fine. But if I change the new call to malloc()
and delete to free(), I get a segmentation fault ( I am expecting the
problem at the call to insert() ).

Not surprising. malloc simply allocates a memory chunk of a specified
size, it doesn't do anything to the contents of that memory. So you're
basically trying to use a garbage pointer as if it pointed to a
well-formed object. If you insist on using malloc-- and it's unlikely
there's a good reason to do so-- then you must follow it with a call to
placement new to construct an actual object:

new(pmap) INT2STRING;

It is then also your responsibility to call the explicitly call the
destructor before you free the memory.
Is it necessary to create the map using new only? Can someone please
quote the section of standard which does not allow this to happen.

Not only is it not necessary to use new, it's not necessary to
dynamically allocate it at all.

int main ()
{
INT2STRING myMap;

// use myMap as you used pmap-> above
}

This has the obvious advantage of not requiring any intervention on your
part related to memory management. No malloc, no free, no new, and no
delete. Generally, unless you need to dynamically allocate the object
it makes sense to use automatic (i.e., on the stack) objects.

Mark
 
V

Victor Bazarov

dragoncoder said:
I have the following code. Plesae have a look.

#include <iostream>
#include <string>
#include <map>
#include <cstdlib>

using namespace std;

typedef map<int,string, less<int> > INT2STRING;
INT2STRING::iterator theIterator;

It's a BAD IDEA(tm) to define things like iterators in the global scope.
int main(int argC,char ** argV)

If you're not going to use 'argC' or 'argV', why declare them?
{
INT2STRING * pmap = NULL;
pmap = new INT2STRING;

Why are the two lines split? Why can't you initialise 'pmap' to the
result of the 'new' expression right where you defined it?
//pmap = static_cast<INT2STRING*>(malloc(sizeof(INT2STRING)));
for(int i =0;i<10;i++)
{
string buff = "Buffer";
pmap->insert(INT2STRING::value_type(i,buff));
}

for(int i=0;i<10;i++)
{
theIterator = pmap->find(i);

If you drop the global declaration of 'theIterator', you could simply
define it here. Remember, the tighter the scope of an object, the better.
if(theIterator != pmap->end() ) cout << (*theIterator).second<<
"\n";
else cout << "[err] ";
}
if (pmap != NULL) delete pmap;

Deleting a null pointer is a NOP. There is no need to check if it's
NULL or not, just delete.
//if (pmap != NULL) free (pmap);
}

The code runs perfectly fine. But if I change the new call to malloc()
and delete to free(), I get a segmentation fault ( I am expecting the
problem at the call to insert() ).

Is it necessary to create the map using new only? Can someone please
quote the section of standard which does not allow this to happen.

'new' doesn't just allocate memory. It creates the object. 'delete'
doesn't just release the memory, it destroys the object. Objects need
to be created (constructed) before they can be used.

What book are you reading that doesn't explain that?

V
 
R

red floyd

dragoncoder said:
Hello all,

I have the following code. Plesae have a look.

#include <iostream>
#include <string>
#include <map>
#include <cstdlib>

using namespace std;

typedef map<int,string, less<int> > INT2STRING;
INT2STRING::iterator theIterator;

int main(int argC,char ** argV)
{
INT2STRING * pmap = NULL;
pmap = new INT2STRING;
//pmap = static_cast<INT2STRING*>(malloc(sizeof(INT2STRING)));
for(int i =0;i<10;i++)
{
string buff = "Buffer";
pmap->insert(INT2STRING::value_type(i,buff));
}

for(int i=0;i<10;i++)
{
theIterator = pmap->find(i);
if(theIterator != pmap->end() ) cout << (*theIterator).second<<
"\n";
else cout << "[err] ";
}
if (pmap != NULL) delete pmap;
//if (pmap != NULL) free (pmap);
}

The code runs perfectly fine. But if I change the new call to malloc()
and delete to free(), I get a segmentation fault ( I am expecting the
problem at the call to insert() ).

Is it necessary to create the map using new only? Can someone please
quote the section of standard which does not allow this to happen.

Out of curiosity, why are you even dynamically allocating the map? Just
declare it local. You don't have to worry about deleteing it then.

When in doubt, if you can avoid new/delete, do so. If you really need
new/delete, then use your favorite smart pointer class.

int main()
{
INT2STRING mymap;

for (int i = 0 ; i < 10; ++i)
mymap.insert(INT2String::value_type(i, string("Buffer")));

// etc....
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top