linux - C++ program compiled in windows produces different output -


i solving problem involved incrementing counter , displaying it. way initialized , incremented variable seemed pretty normal. see counter variable

#include <iostream> #include <cstring>  using namespace std;  int main() {     char s[5];     int counter = 1;      while (cin >> s && (strcmp(s, "*") != 0))     {         cout << "case " << counter++ << ": hajj-e-a";          if (s[0] == 'h')         {             cout << "kbar\n";         }         else if (s[0] == 'u')         {             cout << "sghar\n";         }      } } 

but program mysteriously displayed incorrect result. didn't increment value, started @ 1, properly. see output.

case 1: hajj-e-akbar case 0: hajj-e-asghar case 1: hajj-e-akbar case 0: hajj-e-asghar 

but when tried compiling , running through http://www.tutorialspoint.com/compile_cpp_online.php, uses linux, produced correct results. program accepted online judge.

case 1: hajj-e-akbar case 2: hajj-e-asghar case 3: hajj-e-akbar case 4: hajj-e-asghar 

anyone can point out mystery behind this? why windows-compiled code producing weird results? many thanks!

this buffer overflow. likely, when compile on windows, counter variable follows s[5] variable in memory, this:

+----+----+----+----+----+----+----+----+----+ | ?? | ?? | ?? | ?? | ?? | 01 | 00 | 00 | 00 | +----+----+----+----+----+----+----+----+----+  \________ s[5] ________/ \____ counter ____/ 

since windows little-endian, it's stored 01 00 00 00 instead of 00 00 00 01 might expect. ?? indicates don't know yet what's there - anything.

now, let's enter "hardy" , press enter. in ascii, translates byte sequence 48 61 72 64 79 0d 0a (the last 2 line ending, on unix 0d omitted). cin >> s memory:

1. read in 'h': +----+----+----+----+----+----+----+----+----+ | 48 | ?? | ?? | ?? | ?? | 01 | 00 | 00 | 00 | +----+----+----+----+----+----+----+----+----+ 2. read in 'a': +----+----+----+----+----+----+----+----+----+ | 48 | 61 | ?? | ?? | ?? | 01 | 00 | 00 | 00 | +----+----+----+----+----+----+----+----+----+ 3. read in 'r': +----+----+----+----+----+----+----+----+----+ | 48 | 61 | 72 | ?? | ?? | 01 | 00 | 00 | 00 | +----+----+----+----+----+----+----+----+----+ 4. read in 'd': +----+----+----+----+----+----+----+----+----+ | 48 | 61 | 72 | 64 | ?? | 01 | 00 | 00 | 00 | +----+----+----+----+----+----+----+----+----+ 5. read in 'y': +----+----+----+----+----+----+----+----+----+ | 48 | 61 | 72 | 64 | 79 | 01 | 00 | 00 | 00 | +----+----+----+----+----+----+----+----+----+ 6. read in '\r\n' (or on unix, '\n'), isn't put memory. instead, cin realizes has finished reading, , closes off string '\0': +----+----+----+----+----+----+----+----+----+ | 48 | 61 | 72 | 64 | 79 | 00 | 00 | 00 | 00 | +----+----+----+----+----+----+----+----+----+  \________ s[5] ________/ \____ counter ____/ 

whoops! overwrote counter!

why work correctly on linux? either linux doesn't place 2 variables adjacent in memory, or linux system big-endian, mean memory instead laid out this:

+----+----+----+----+----+----+----+----+----+ | ?? | ?? | ?? | ?? | ?? | 00 | 00 | 00 | 01 | +----+----+----+----+----+----+----+----+----+ 

so if read in 5 characters, final null terminator replaces 0 there. of course, if cause, reading in 6 characters mess things up.

and how fix it? problem that, hold string of length n, character array needs have length of n+1. this:

char s[6]; 

or better, use string:

std::string s; 

(for need #include <string>.)


Comments