std::map implementation differs between linux and windows - c++

The following code acts differently after being compiled in linux and Visual Studio 2015.
#include <map>
#include <iostream>
using namespace std;
int main(void)
{
map<int, int> map1;
int keyCount = 2;
for (int i = 0; i < keyCount; i++)
{
map1[i] = map1.size();
}
for (auto value : map1)
{
cout << "key: " << value.first << " value: " << value.second << endl;
}
return 0;
}
The result in Visual Studio :
key: 0 value: 0
key: 1 value: 1
The result in linux compiled with g++ -std=c++11 -Wall -pedantic
key: 0 value: 1
key: 1 value: 2
I have two questions:
As far as I understand c++, the VS implementation is right.
If I change the code to:
for (int i=0; i < keyCount; i++)
{
unsigned int mapSize= map1.size();
map1[i] = mapSize;
}
then it behaves like Visual Studio on both platforms.
Shouldn't the code always behave like this?
2.What Visual Studio compiler settings can I use to make sure that VS will compile the same as Linux?
I am working on Windows, but have an assignment that must work on Linux.

map1[i] = map1.size();
expands to
(map1.operator[](i)) = (map1.size());
C++ makes no guarantees about whether operator[] or size is called first, since both are operands to the assignment expression. Both compilers are correct.
You should split your expression into two statements if you expect one behavior or the other.

Related

Mixing C++ Containers with C language structs

I have spent 2 days chasing an issue involving C++ container, std::list, and C-Style structs. Is the following undefined behavior (Note the type for the std::list parameter)?
#include <list>
#include <iostream>
using std::cout;
using std::endl;
struct Point_Struct
{
int x;
int y;
};
typedef struct Point_Struct Point;
int main()
{
std::list<Point> line;
Point p;
p.x = 3;
p.y = 10;
line.push_back(p);
cout << "Size of container: " << line.size() << "\n";
// Here's the issue:
line.pop_back();
// The size should be zero.
cout << "Size of container after pop_back(): " << line.size() << "\n";
return 0;
}
I ran this on Visual Studio 2017 and I get an exception error, 0xC0000005, (memory access) on the call to pop_back.
The exception is also thrown on any method that changes the ordering of the items in the list, such as assignment and sort.
If I change the type of line to std::list<Point_Struct>, there are no exceptions thrown.
Note: The issue was found in a larger program. The code above illustrates the root cause of the issue: std::list<typedef struct> vs. std::list<struct>
Note: The exception is thrown in VS2017 debug mode but not in release mode.
Sorry, but multiple questions follow:
Is there anything in standard C++ (11 or later) declaring undefined
behavior for using a typedef instead of a struct as the template
parameter for std::list?
Would this be a Visual Studio bug?
I haven't tried on G++ or other compilers.
Edit 1: VS2017 version info
Microsoft Visual Studio Professional 2017
Version 15.9.14
Installed product: Visual C++ 2017 - 00369-60000-00001-AA071
Compilation Info
Configuration: Debug
Platform: Win32
Warning Level: Level3 (/W3)
Optimization: Disabled (/Od)
Enable C++ Exception: Yes (/EHsc)
Basic Runtime Checks: Both (/RTC1)
Disable Language Extensions: No
Conformance mode: No
Platform
Platform: Windows 7
I compiled and ran your code with g++ 11 in Eclipse (Ubuntu 18) and it worked perfectly,
Output:
Size of container: 1
Size of container after pop_back(): 0
Have you tried/is it possible to swap typedef for using? This might fix it:
#include <list>
#include <iostream>
using std::cout;
using std::endl;
struct Point_Struct
{
int x;
int y;
};
using Point = Point_Struct;
int main()
{
std::list<Point> line;
Point p;
p.x = 3;
p.y = 10;
line.push_back(p);
cout << "Size of container: " << line.size() << "\n";
// Here's the issue:
line.pop_back();
// The size should be zero.
cout << "Size of container after pop_back(): " << line.size() << "\n";
return 0;
}

Declaring a vector throws a runtime error in NetBeans

I'm trying to learn about vectors in C++, but just trying to declare one throws a runtime error in NetBeans.
Error: Run failed (exit value -1, 073, 741, 511, total time 51 ms)
PS: The code works perfectly in Eclipse.
#include <iostream>
#include <vector>
using namespace std;
int main() {
// create a vector to store int
vector<int> vec;
int i;
// display the original size of vec
cout << "vector size = " << vec.size() << endl;
// push 5 values into the vector
for (i = 0; i < 5; i++) {
vec.push_back(i);
}
// display extended size of vec
cout << "extended vector size = " << vec.size() << endl;
// access 5 values from the vector
for (i = 0; i < 5; i++) {
cout << "value of vec [" << i << "] = " << vec[i] << endl;
}
// use iterator to access the values
vector<int>::iterator v = vec.begin();
while (v != vec.end()) {
cout << "value of v = " << *v << endl;
v++;
}
return 0;
}
I have tested on my system (latest GCC and NB dev build) and it works without any problem. The desired output is shown. It also runs fine from command line.
Therefore I assume it's more a configuration or system related problem. But without any further informations it's impossible to find the root cause.
More information please:
What OS / Environment are you using?
What Compiler (and versions) do you have?
What version of Netbeans do you use?
Do other project's work?
Here's some first aid you can try:
Create a new C++ Project (C++ Application). It already includes a blank main() function. Run this and check if there's still an error
Create a simple .cpp file and build it from command line (don't involve any IDE). Does it work this way?
Build and your source file without IDE. From Commandline: g++ <your filename>.cpp
Review your compiler settings (Tools -> Options -> C/C++ at Build Tools). Especially use the Version button and check if everything is right.
Windows only: Make sure you have the correct make executable selected in the compiler settings
Have a look at the IDE's log (View -> IDE Log). Are there any problems mentioned?
Run in Debug without any breakpoint. This is going to stop the execution on any runtime error.

Same code correct on Mac, incorrect on Linux [duplicate]

This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 5 years ago.
I am running into a problem which has thrown me for a loop (no pun intended). I was trying to illustrate how overloaded operators can enhance the readability of code quite a bit. In order to do so, I wrote a simple class called 'cow' (no special meaning). When I compile the code on a Mac, it compiles cleanly and executes as expected.
The exact same code compiled on a Linux box (Ubuntu) also compiles cleanly, but executed with an incorrect result.
Somewhere, I must be missing something obvious, but I'm not seeing it.
Here is the code:
#include <iostream>
#include <sstream>
using namespace std;
class cow {
public:
cow();
cow(int i);
int add(int a);
int add(string str);
int get() const;
private:
int i;
};
cow::cow() {
i = 0;
}
cow::cow(int j) {
i = j;
}
int cow::add(string str) {
stringstream s;
int num;
s << str;
s >> num;
return i += num;
}
int cow::add(int a) {
return i += a;
}
int cow::get() const {
return i;
}
int main() {
cow i(15);
cout << i.get() << " : " << i.add(15) << " : " << i.add("-15.0");
return 0;
}
Compiling (g++ -Wall -o cow cow.cpp) yields no warnings and no errors and creates an executable.
Executing the program on the Linux box yields:
$ ./cow
15 : 15 : 0
Executing the program on a Mac yields:
$ ./cow
15 : 30 : 15
The C++ compiler on the Mac is:
$ g++ --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.38)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
The C++ compiler on the Linux box is:
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Any suggestions as to what is causing this behavior is appreciated, as are ways to fix it on the Linux box!
Thanks,
Kees
You're getting an undefined behavior because you change the state of the instance several times within one expression. By the C++ standard, your calls to i in this line:
cout << i.get() << " : " << i.add(15) << " : " << i.add("-15.0");
could be performed in any order.
It is just your luck the Mac's compiler performs the calls left to right as you expect.
To get the reliable result you should evaluate those calls sequentially, like:
auto a1 = i.get();
auto a2 = i.add(15);
auto a3 = i.add("-15.0);
cout << a1 << " : " << a2 << " : " << a3;
You're running into undefined behaviour in this line:
cout << i.get() << " : " << i.add(15) << " : " << i.add("-15.0");
It's up to the compiler which order it evaluates i.get (), i.add(15) and i.add("-15.0") - it's not normally a problem unless evaluating one of them would change the output of another of them (which is the case here - i changes).
As you're using different compilers (g++ on Linux, clang on Mac), each is evaluating in different orders.

Iterating boost::icl::interval_set

I am iterating a boost interval_set<unsigned_int>, and I was expecting each iterator to be a boost interval, whose values would be accessed with the upper and lower methods:
boost::icl::interval_set<unsigned int> outages;
// ...
// Insert intervals into the database
for(boost::icl::interval_set<unsigned int>::iterator it =
outages.begin(); it != outages.end(); it++){
DATA_ACQUISITION::InsertInterval(db, it->lower(),
it->upper())
}
But I am receiving errors at both lower and upper methods: Method ... could not be resolved, which suggests me that the iterator is not pointing to an interval at all.
So, what am I really iterating here? How to iterate though the intervals inserted into the interval_set?
EDIT: Adding SSCCE:
#include <boost/icl/interval_set.hpp>
#include <iostream>
#include <vector>
int main() {
boost::icl::interval_set<unsigned int> outages;
for(unsigned int i=0; i<5; i++){
outages += boost::icl::discrete_interval<unsigned int>::closed(
(i*10), ((i*10) + 5));
}
for(boost::icl::interval_set<unsigned int>::iterator it =
outages.begin(); it != outages.end(); it++){
std::cout << it->lower() << boost::icl::upper(*it);
}
return 0;
}
Additional info:
I am currently not adding any library ti the linker (until now, no error suggested I needed that, and haven't found which argument should I add to the -l anyway)
Compiler g++ 4.8.1
Boost version: 1.46
In latest boost, at least, this is no issue:
Live On Coliru
#include <boost/icl/interval_set.hpp>
#include <iostream>
int main() {
typedef boost::icl::interval_set<unsigned int> set_t;
typedef set_t::interval_type ival;
set_t outages;
outages.insert(ival::closed(1,1));
outages.insert(ival::open(7,10));
outages.insert(ival::open(8,11));
outages.insert(ival::open(90,120));
for(set_t::iterator it = outages.begin(); it != outages.end(); it++){
std::cout << it->lower() << ", " << it->upper() << "\n";
}
}
Prints
1, 1
7, 11
90, 120
If older boost versions don't directly support the members, try the free functions:
std::cout << lower(*it) << ", " << upper(*it) << "\n";
Here, ADL finds the overloads declared in the boost::icl namespace
Finally, I realised that the errors where not from compilation but from Eclipse CDT, and have no effect at all.

gcc and clang both cannot compile a loop program

I've been unable to get gcc and clang to compile this simple program I've written for an exercise in a textbook. The objective of this program is to accept 2 simple integer values from standard input, and then print out the 2 values to standard output. The program I have written is as follows:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
inline void keep_window_open() {char ch; cin>>ch;}
int main()
{
vector<int> vect;
int number;
int i = 0 ;
while (cin >> number && vect.size() < 3)
{
vect.push_back(number);
}
cout << vect << '\n';
}
When I compile the program with gcc, I get the following error:
Kohs-MacBook-Pro:Learning_C++ Kohaugustine$ gcc drill_chapter_4_v2.cpp -o drill_chapter_4_v2 -stdlib=libstdc++ -lstdc++
drill_chapter_4_v2.cpp:21:8: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'vector<int>')
cout << vect << '\n';
~~~~ ^ ~~~~
The same error "invalid operands to binary expression" also happens when I try using clang.
Does anyone know what exactly is the problem here?
I'm really new to C++ and although I previously had experience with Python, moving to C++ is so different, and I've yet to take any formal introductory courses in programming, so please bear with me if this is a very simple problem. I would greatly appreciate any help to move forward!
Thank you!
You can't print an entire vector like that. Use a loop:
for (auto value : vect)
std::cout << value << ' ';
There is no operator<<(std::ostream, std::vector<int>) in the C++ standard library.
One could write one, such as this:
std::ostream& operator<<(std::ostream& os, std::vector<int> v)
{
for(auto i : v)
{
os << i << ' ';
}
return os;
}
I should point out that iterating over the vector in situ is the typical solution, so:
for(auto i : vect)
{
std::cout << i << ' ';
}
would be what I expect to see in the code.
Change this part of the code
while (cin >> number && vect.size() < 3)
{
vect.push_back(number);
}
cout << vect << '\n';
the following way
while ( vect.size() < 3 && cin >> number )
{
vect.push_back( number );
}
for ( int x : vect ) cout << x << '\n';
As for the error then there is no operator << for vectors. Either you should define it yourself or print out each element of a vector yourself using as shown above for example the range based for loop.