Code: Show/Hide ostrstream tout();
tout.write((char*)&next_uid, 4); num = 0xCF9328F6; tout.write((char*)&num, 4); for (i = 0; i < NUM_PLAYERS; i++) { len = strlen(players[i].name); tout.write(players[i].name, len); //Access violation here on second run-through NULLS(0x100 - len); } |
Code: Show/Hide #define NULLS(size) \
tout.seekp(size, ios::cur); |
Code: Show/Hide class Player
{ public: Player(); ~Player(); void reset(); char name[30]; int stable; int enable, human, civ; char ai[_MAX_FNAME]; char *aifile; //mmapping of AI file for exporting unsigned long resources[4]; //gold, wood, food, stone int dis_tech[0x1E], dis_unit[0x1E], dis_bldg[0x14]; int ndis_t, ndis_u, ndis_b; float unknown[6]; float pop; float camera[2]; short u1, u2; bool avictory; char diplomacy[9]; int color; SVector <Unit> units; }; |
Mr Ekted wrote: |
Add this just before the call to tout.write(players[i].name, len):
printf("%08x\n", players[i].name); |
Code: Show/Hide FILE *fDebug = fopen("debug.log", "w+");
if (fDebug) { fprintf(fDebug, "%08x\n", players[i].name); fclose(fDebug); } |
Dust wrote: |
I've never used ostrstream before, I was looking around for info on it and it seemed the general consensus was that it was deprecated, and you should use ostringstream instead. |
Code: Show/Hide streampos strstreambuf::seekoff(streamoff off, ios::seek_dir dir, int mode)
{ char * tptr; long offset = EOF; // default return value //cut out ios::in funcs if (mode & ios::out) { if (!epptr()) { if (strstreambuf::overflow(EOF)==EOF) return EOF; } switch (dir) { case ios::beg : tptr = pbase(); break; case ios::cur : tptr = pptr(); break; case ios::end : tptr = epptr(); break; default: return EOF; } tptr += off; offset = tptr - pbase(); if (tptr < pbase()) return EOF; if (tptr > epptr()) { if (x_dynamic) { x_bufmin = __max(x_bufmin, (tptr-pbase())); if (strstreambuf::doallocate()==EOF) return EOF; } else return EOF; } pbump(tptr-pptr()); } return offset; } |
Cyan~Fire wrote: |
Yeah, I've seen that before, but sadly ostringstream uses std::strings, which are a part of STL, which I'm not using for reasons Ekted would appreciate ![]() |
Code: Show/Hide #pragma pack(1)
struct MyData { unsigned long next_uid; unsigned long num; char name[NUM_PLAYERS][256]; // etc. }; #pragma Pack() function () { int i; MyData data; memset(&data, 0, sizeof(data)); data.next_uid = next_uid; data.num = 0xCF9328F6; for (i = 0; i < NUM_PLAYERS; i++) strcpy(data.name[i], players[i].name); // blah blah blah } |
Code: Show/Hide char buff[256]; ostrstream tout(); tout.write((char*)&next_uid, 4); num = 0xCF9328F6; tout.write((char*)&num, 4); for (i = 0; i < NUM_PLAYERS; i++) { memset( buff, 0, sizeof(buff) ); strncpy( buff, players[i].name, sizeof(buff) ); tout.write( buff, sizeof(buff) ); } |
Macaub wrote: |
* If you're working with strings, treat them as strings. If working with binary data, treat it as binary data. Your use of write() to write the name is inconsistent with this approach and is sure to cause nothing but headaches one day. The write() function treats the buffer as binary data, hence there is NO null terminator added to the "string". Sure, in this case your intention is to fill the remaining space with 0's, but in general this is asking for trouble. If you truly want to treat it as a string, you can simply use the output operator (<<). |
Macaub wrote: |
* Lastly, if you KNOW how big NUM_PLAYERS is, and you KNOW that you want each player's name to be stored in a 256-byte buffer, there's no need for a dynamically reallocated/resized array. Either create a static packed array (as in Ekted's example), or if the buffer needs to be dynamic, allocate your known size in one fell swoop instead of reallocating and re-free'ing little chunks over and over. |