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
Post a Comment