473,401 Members | 2,127 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,401 software developers and data experts.

Broken STL implementation?

Is my implementation correct to print only a blank line when the
following program is compiled and run?

#include <iostream>
#include <map>

int main()
{
std::map< const char *, std::string > m;
m["foo"]="bar";
std::cout << m["foo"] << std::endl;
return 0;
}

g++ prints "bar", which is of course the behavior I want. If this is
a(nother) problem with my implementation, what, if anything, can I do
to work around it?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #1
9 1141
Christopher Benson-Manica wrote:
Is my implementation correct to print only a blank line when the
following program is compiled and run?

#include <iostream>
#include <map>

int main()
{
std::map< const char *, std::string > m;
m["foo"]="bar";
std::cout << m["foo"] << std::endl;
return 0;
}

g++ prints "bar", which is of course the behavior I want. If this is
a(nother) problem with my implementation, what, if anything, can I do
to work around it?


There is no guarantee that the first "foo" and the second "foo" are
the same constant string. Both implementations are, therefore, correct.

The work-around is to ensure that you're passing the same pointer value
both times:

int main()
{
..
const char *pfoo = "foo";
m[pfoo] = "bar";
std::cout << m[pfoo] << std::endl;
}

Victor
Jul 22 '05 #2
On Wed, 18 Aug 2004 16:09:02 +0000 (UTC), Christopher Benson-Manica
<at***@nospam.cyberspace.org> wrote:
Is my implementation correct to print only a blank line when the
following program is compiled and run?

#include <iostream>
#include <map>

int main()
{
std::map< const char *, std::string > m;
Ok, so your map is flawed already - you can't < compare pointer values
unless those pointers point into the same object (or array).
m["foo"]="bar";
std::cout << m["foo"] << std::endl;
The second "foo" may or may not have the same address as the first one
- it's unspecified. So that may or may not have undefined behaviour
(which is what you're seeing).
return 0;
}

g++ prints "bar", which is of course the behavior I want. If this is
a(nother) problem with my implementation, what, if anything, can I do
to work around it?


I think you way to have the map sorted according to the contents of
the string, not the pointer value? If so, then you need something
like:

#include <cstring>

struct strcmper
{
typedef bool result_type;
typedef const char* first_argument_type;
typedef const char* second_argument_type;
bool operator()(const char* lhs, const char* rhs) const
{
return std::strcmp(lhs, rhs) < 0;
}
};

//...
std::map< const char *, std::string, strcmper > m;

Tom
Jul 22 '05 #3
Christopher Benson-Manica wrote:
Is my implementation correct to print only a blank line when the
following program is compiled and run?

#include <iostream>
#include <map>

int main()
{
std::map< const char *, std::string > m;
m["foo"]="bar";
std::cout << m["foo"] << std::endl;
return 0;
}

g++ prints "bar", which is of course the behavior I want. If this is
a(nother) problem with my implementation, what, if anything, can I do
to work around it?

This is not a problem with your library. The following code will yield a
blank line with g++, and I venture to say, on any standard complient
compiler:

#include <iostream>
#include <map>

int main()
{
char foo1 [4] = "foo";
char foo2 [4] = "foo";
std::map< const char *, std::string, std::less< const char * > m;
m[foo1]="bar";
std::cout << m[foo2] << std::endl;
return 0;
}

Back to your code:
std::map< const char *, std::string > m;


This is a bas idea: map operations will call operator< which is supposed to
be a weak total ordering. The standard makes no requirement that this holds
for comparision of const char *. Thus

std::map< const char *, std::string, std::less< const char * > m;

is better. However, it is clearly not what you want.

What happens is that your map m just stores a pointer to char and not a
copy of that string. Moreover, you donot compare the entries by their
values as strings but just by their address. Since foo1 and foo2 point to
different memory locations, the second programm prints a blank line. That
g++ prints "bar" for your code indicates that g++ folded the two occurences
of "foo" in your code to the same memory location: this tells us a little
bit about g++ handles string constants.

Recommendation: fix your code by using std::string for the keys in the map,
as well.
Best

Kai-Uwe
Jul 22 '05 #4
Christopher Benson-Manica <at***@nospam.cyberspace.org> wrote in
news:cf**********@chessie.cirr.com:
Is my implementation correct to print only a blank line when the
following program is compiled and run?
Yes.
#include <iostream>
#include <map>

int main()
{
std::map< const char *, std::string > m;
Keep in mind that this means that std::map is using std::less<const char
*> to determine equivalence. So the map will be comparing pointer
values, not what they're pointing _at_....
m["foo"]="bar";
This string literal "foo" lives at some memory location somewhere. Say,
0x00000004. So you're effectively doing:

m[reinterpret_cast<const char *>(0x00000004)] = "bar";
std::cout << m["foo"] << std::endl;
This string literal "foo" _may_ live at a different memory location.
Say, 0x00000008. So you're effectively doing:

m[reinterpret_cast<const char *>(0x00000008)] = "bar";

A different index than the first one....
return 0;
}

g++ prints "bar", which is of course the behavior I want. If this is
a(nother) problem with my implementation, what, if anything, can I do
to work around it?


Make your map: std::map<std::string, std::string>. A second alternative
is to supply your own comparison functor that knows to follow the pointer
to the actual string and compare those.

g++ is probably doing a string folding optimization where the compiler
notices that "foo" and "foo" are the same string literal, thus can share
the same memory location.
Jul 22 '05 #5
tom_usenet wrote in news:kc********************************@4ax.com in
comp.lang.c++:

Ok, so your map is flawed already - you can't < compare pointer values
unless those pointers point into the same object (or array).


No, the map uses std::less< char const * > which is required to
handle such cases 20.3.3/8.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #6
"Kai-Uwe Bux" <jk********@gmx.net> wrote in message
news:cg**********@news01.cit.cornell.edu...
<snip>
std::map< const char *, std::string > m;
This is a bas idea: map operations will call operator< which is supposed

to be a weak total ordering. The standard makes no requirement that this holds for comparision of const char *. Thus

std::map< const char *, std::string, std::less< const char * > m;

is better. However, it is clearly not what you want.

<snip>

FYI, std::map's third template argument defaults to std::less<Key>. Your
"correction" is equivalent to the original code.

--
David Hilsee
Jul 22 '05 #7
David Hilsee wrote:
"Kai-Uwe Bux" <jk********@gmx.net> wrote in message
news:cg**********@news01.cit.cornell.edu...
<snip>
> std::map< const char *, std::string > m;


This is a bas idea: map operations will call operator< which is supposed

to
be a weak total ordering. The standard makes no requirement that this

holds
for comparision of const char *. Thus

std::map< const char *, std::string, std::less< const char * > m;

is better. However, it is clearly not what you want.

<snip>

FYI, std::map's third template argument defaults to std::less<Key>. Your
"correction" is equivalent to the original code.


Thanks!
Kai-Uwe Bux
Jul 22 '05 #8
On 18 Aug 2004 21:11:57 GMT, Rob Williscroft <rt*@freenet.co.uk>
wrote:
tom_usenet wrote in news:kc********************************@4ax.com in
comp.lang.c++:

Ok, so your map is flawed already - you can't < compare pointer values
unless those pointers point into the same object (or array).


No, the map uses std::less< char const * > which is required to
handle such cases 20.3.3/8.


Interesting, I didn't realise that std::less ever did anything beyond
<.

Tom
Jul 22 '05 #9
Christopher Benson-Manica wrote:
Is my implementation correct to print only a blank line when the
following program is compiled and run?

#include <iostream>
#include <map>

int main()
{
std::map< const char *, std::string > m;
m["foo"]="bar";
std::cout << m["foo"] << std::endl;
return 0;
}

g++ prints "bar", which is of course the behavior I want. If this is
a(nother) problem with my implementation, what, if anything, can I do
to work around it?


The above is not a well-defined behaviour.Use map<string, string> instead.
The two string literals used, may have different addresses.


Regards,

Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

28
by: Grant Edwards | last post by:
I finally figured out why one of my apps sometimes fails under Win32 when it always works fine under Linux: Under Win32, the pickle module only works with a subset of floating point values. In...
42
by: cody | last post by:
public DateTime Value { get { try { return new DateTime(int.Parse(tbYear.Text), int.Parse(tbMonth.Text), int.Parse(tbDay.Text)); } catch (FormatException)
205
by: Jeremy Siek | last post by:
CALL FOR PAPERS/PARTICIPATION C++, Boost, and the Future of C++ Libraries Workshop at OOPSLA October 24-28, 2004 Vancouver, British Columbia, Canada http://tinyurl.com/4n5pf Submissions
19
by: newbiecpp | last post by:
I am looking for a C++ unit testing program. I googled and found there are quite a few there, such as CppTest, C++Test, and DejaGnu. Can someone give me a recommendation among these programs? I...
11
by: Peter Pichler | last post by:
A colleague encountered an interesting problem. Suppose we have a C function like this: void WRITE_THING(void* addr, THING t) { memcpy(addr, &t, sizeof t); } to copy a THING to any byte...
10
by: Larry Hastings | last post by:
I'm an indie shareware Windows game developer. In indie shareware game development, download size is terribly important; conventional wisdom holds that--even today--your download should be 5MB or...
1
by: Chris Mullins | last post by:
We've been using the SSLStream class found in System.Net.Security to build a giant Sockets server that provides TLS encryption at the channel leve. Before .Net 2.0, we used an open-source...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.