Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Input stream: operation order in Solaris vs. Linux

I have a very simple test program that uses istringstreams to read in integers from a std::string. The code is:

std::map<int, int> imap;
int idx, value;
std::string str("1 2 3 4 5 6 7 8");
istringstream is(str);
while(is >> idx >> imap[idx]){
    cout << idx << " " << imap[idx] << endl;
}
cout << endl;

std::map<int, int>::iterator itr;
for(itr = imap.begin(); itr != imap.end(); itr++){
    cout << itr->first << " " << itr->second << endl;
}

When I run this on Solaris 10, it produces the following output:

1 2
3 4
5 6
7 8

1 2
3 4
5 6
7 8

However, when I run it under CentOS 7, I get:

1 0
3 0
5 0
7 0

1 4
3 6
5 8
7 0
4204240 2

Does anyone know why it would be different under Linux than under Solaris? It's obviously reading in the value into the map before reading into the index for the map, but I don't know why. I can make it work under Linux by changing the code slightly:

std::map<int, int> imap;
int idx, value;
std::string str("1 2 3 4 5 6 7 8");
istringstream is(str);
while(is >> idx >> value){
    imap[idx] = value;
    cout << idx << " " << imap[idx] << endl;
}

std::map<int, int>::iterator itr;
for(itr = imap.begin(); itr != imap.end(); itr++){
    cout << itr->first << " " << itr->second << endl;
}

I know it's a valid fix, but I have people around me who want to know why it is different. We are migrating from Solaris to Linux and when things like this come up, they want to know why. I don't know why so I'm asking for guidance.

like image 471
Diana Coppenbarger Avatar asked Jan 14 '15 21:01

Diana Coppenbarger


People also ask

How do I find system calls in Solaris?

The Solaris OS keeps a list of system calls in /usr/include/sys/syscall.h. Linux maintains the same information in /usr/include/asm/unistd.h. (Note that both Linux and the Solaris OS have unistd.h and syscall.h files, and that in some cases, the files agree in content.)

How are signals handled on Solaris OS and Linux?

On both the Solaris OS and Linux, signals are handled when a non-held, non-ignored signal is found pending for a thread returning from kernel to user mode. On both systems, SIGKILL and SIGSTOP take priority over other signals. Otherwise, on Solaris signals are handled in an undocumented order (lowest signal number first).

How many I/O streams does Linux use?

Linux shells use three standard I/O streams, each of which is associated with a well-known file descriptor: This series of tutorials helps you learn Linux system administration tasks.

What are the similarities between Solaris and Linux operating systems?

Both the Solaris OS and Linux support System V IPC (shared memory, message queues, and semaphores). Both systems also support pipes and the real-time shared memory operations ( shm_open (), shm_unlink (), and so on). Both systems support the tmpfs file system (using memory and swap space for files).


1 Answers

is >> idx >> imap[idx]

This expression is equivalent to

operator>>(operator>>(is, idx), imap.operator[](idx))

The evaluations of arguments to the same function are unsequenced relative to each other; either operator>>(is, idx) or imap.operator[](idx) may be evaluated first (that is, either is >> idx or imap[idx] may be evaluated first). If the latter is evaluated first, then the result is an lvalue referring to the value corresponding to the old value of idx in the map; it is this value that will be overwritten by the second read, and not the value corresponding to the new value of idx.

The modified code fixes this by ensuring that idx is read before imap[idx] is accessed.

like image 192
Brian Bi Avatar answered Sep 24 '22 13:09

Brian Bi