Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Super Dude
Jan 23, 2005
Do the Jew

Vanadium posted:

Can you post the relevant parts of proj1

Edit: Like, for example enough code so that it actually compiles, and ideally produces the output that is not to your expectations.

code:
#include <iostream>
#include <string>
#include "StackList.h"
#include "QueueArray.h"

using namespace std;

int main(int argc, const char* argv[])
{
	int floors, size;
	string temp;
	StackList<string> comments;

	cin >> size;
	cin >> floors;
	int count=0;
	int arraySize = (floors*size*size);
	char* building = new char[arraySize];

	while(getline(cin,temp,'\n'))
	{
		if(temp[0]=='#')
		{ 
			comments.push(temp);
		}
		else
		{
			for(int i=0;i<size;i++)
			{
				building[count]=temp[i];
				if(count==0)
					cout << building[0] << endl;
				count++;
			}
		}	
		
	}

	cout << size << endl << floors << endl;
	string c = " ";
	count = 0;
	while(count<arraySize)
	{
		for(int t=0;t<size;t++)
		{
			for(int u=0;u<size;u++)
			{
				cout << building[count];
				count++;
			}
			cout << endl;
		}		
	}	

	return 0;
}
That tries to do what I want, and should output what I want to out.txt. I was able to open out.txt in vim, it wouldn't open in gedit. It cut off the last line of the map on the very bottom. I realize the comments aren't in there. I don't know what the hell those ^@ things are.

code:
  1 ^@
  2 8
  3 3
  4 ^@^@^@^@^@^@^@^@
  5 XXXXXXXX
  6 X......H
  7 X..X.XXX
  8 X.X..X.X
  9 X..XX..X
 10 X......X
 11 X......X
 12 XXX.vXXX
 13 XXXXXXXX
 14 X......X
 15 X..X.XXX
 16 X.X..X.X
 17 X..XX..X
 18 X......X
 19 X^....SX
 20 XXX.vXXX
 21 XXXXXXXX
 22 X..X.^XX
 23 X....XXX
 24 X..X...X
 25 P..X...X
 26 X...X..X
 27 X...X..X

Adbot
ADBOT LOVES YOU

Vanadium
Jan 8, 2005

The ^@ are bytes with value 0. gedit does not know what the hell to do with them.

Edit: The cin >> floors just reads the number, and leaves the newline in the stream. So the first getline makes temp an empty string. So reading temp[0], and later temp[i], is undefined behaviour.

Vanadium fucked around with this message at 00:47 on Jan 28, 2009

Super Dude
Jan 23, 2005
Do the Jew

Vanadium posted:

The ^@ are bytes with value 0. gedit does not know what the hell to do with them.

Edit: The cin >> floors just reads the number, and leaves the newline in the stream. So the first getline makes temp an empty string. So reading temp[0], and later temp[i], is undefined behaviour.

I've never used it, but would cin.flush() get rid of the newline?

edit: It seems to be reading that entire first line of the top row of the map as ^@. I've tried cin.flush() and cin.clear(), and neither of those do anything helpful.

edit2: I added another getline right after I read in the two numbers, and before I started reading in the rest of the stuff, and that fixed it. That seems like a really crappy way to fix it though. :(

Super Dude fucked around with this message at 02:27 on Jan 28, 2009

Vanadium
Jan 8, 2005

You could use std::cin.ignore(std::numeric_limits<int>::max(), '\n'); instead of that getline, or you could just use std::getline in the first place instead of using operator>>, and then use std::strtol or something to read the numbers from the string.

cin.flush() does not do anything that I am aware of, and cin.clear() clears the error bits, not the buffer or anything.

Super Dude
Jan 23, 2005
Do the Jew

Vanadium posted:

You could use std::cin.ignore(std::numeric_limits<int>::max(), '\n'); instead of that getline, or you could just use std::getline in the first place instead of using operator>>, and then use std::strtol or something to read the numbers from the string.

cin.flush() does not do anything that I am aware of, and cin.clear() clears the error bits, not the buffer or anything.

But getline grabs it as a string, right? I needed them to be ints.

Vanadium
Jan 8, 2005

Super Dude posted:

But getline grabs it as a string, right? I needed them to be ints.

That is where strtol comes in.

sklnd
Nov 26, 2007

NOT A TRACTOR

Vanadium posted:

You could use std::cin.ignore(std::numeric_limits<int>::max(), '\n'); instead of that getline, or you could just use std::getline in the first place instead of using operator>>, and then use std::strtol or something to read the numbers from the string.

cin.flush() does not do anything that I am aware of, and cin.clear() clears the error bits, not the buffer or anything.
I'd imagine cin is similar to input streams in c, where fflush() behavior on input streams is undefined (flush is defined as writing the stream to disk. flush in the case of an input stream makes no sense). IIRC fflush(stdin) will work on Windows, but is terrible non-portable programming.

Vanadium
Jan 8, 2005

Does the standard make any guarantees that I can allocate arrays of a certain size? Obviously at some point I am going to run into memory restrictions and I guess page sizes or whatever, but is there any defined minimum on allowed array sizes?

Bitruder
Nov 29, 2003

Majoring in connect the dots and colouring
I'm on Linux and I need to copy a temporary file to the working directory (via C++). I make the temporary file via mkstemp() and on my machine, it ends up in /tmp. My working directory is on the /home partition which differs from /tmp. When I tried using the system rename call, I got the error "Invalid cross-device link". So I tried using boost::filesystem but I'm getting the same error!

Any suggestions?

EDIT: I got it to work by using boost::filesystem::copy_file() followed by boost::filesystem::remove().

Bitruder fucked around with this message at 17:03 on Jan 28, 2009

covener
Jan 10, 2004

You know, for kids!

Bitruder posted:

I'm on Linux and I need to copy a temporary file to the working directory (via C++). I make the temporary file via mkstemp() and on my machine, it ends up in /tmp. My working directory is on the /home partition which differs from /tmp. When I tried using the system rename call, I got the error "Invalid cross-device link". So I tried using boost::filesystem but I'm getting the same error!

Any suggestions?

You can't rename a file from one filesystem to the other, you need to copy it if stat tells you the device # is different on the destination filesystem. There is no syscall that tries to rename and copies the contents if necessary

Poop Toucher
Jul 12, 2006

"I sometimes like to feel the poop as it leaves my hole."
Does anyone know of any good, preferably free, C++ IDEs that work for Vista? I tried CodeBlocks with the nightly builds and nothing happens when I try to build/run the program.

raminasi
Jan 25, 2005

a last drink with no ice

shoe posted:

Does anyone know of any good, preferably free, C++ IDEs that work for Vista? I tried CodeBlocks with the nightly builds and nothing happens when I try to build/run the program.

Visual C++ Express?

Poop Toucher
Jul 12, 2006

"I sometimes like to feel the poop as it leaves my hole."
Thanks.

WalletBeef
Jun 11, 2005

I'm using the Xerces C++ XML parser, (the XercesDOMParser class) to parse a 60 meg xml file and I have a question.

Here is the declaration of my parser:

code:

void parseSomeStuff (const wchar_t* filePath)
{

    std::auto_ptr<XercesDOMParser> parser (new XercesDOMParser());
    parser->setValidationScheme(XercesDOMParser::Val_Never);
    parser->setDoNamespaces(false);
    parser->setDoSchema(false);
    parser->parse(filePath);

    // Do parsing stuff after this line.
}
After the call to parse, the memory usage jumps by 742 Megs.

Is there a more lightweight class I can use to parse this file without sacrificing too much in the speed department?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
You're probably going to have to use SAX (more like SUX) if you want to keep memory usage to a minimum.

newsomnuke
Feb 25, 2007

Vanadium posted:

Does the standard make any guarantees that I can allocate arrays of a certain size? Obviously at some point I am going to run into memory restrictions and I guess page sizes or whatever, but is there any defined minimum on allowed array sizes?
No guarantees. 0 is the defined minimum request size, but this can still fail.

Vanadium
Jan 8, 2005

Thanks. I am somewhat disappointed, but I am not sure what I expected.

WalletBeef
Jun 11, 2005

Avenging Dentist posted:

You're probably going to have to use SAX (more like SUX) if you want to keep memory usage to a minimum.

Yea, SAX does suck, but it did the job well. I was able to reduce that jump in memory from by about 90%. Yay.

Fehler
Dec 14, 2004

.
Can anybody explain to me why the delete[] here causes a heap exception? uinfo is a struct, uinfo.xx is a char* and yy is a wchar_t*.

code:
uinfo.xx = new char[wcslen(yy)];
wcstombs(uinfo.xx, yy, strlen(uinfo.xx));
delete[] uinfo.xx;

Standish
May 21, 2001

Fehler posted:

Can anybody explain to me why the delete[] here causes a heap exception? uinfo is a struct, uinfo.xx is a char* and yy is a wchar_t*.

code:
uinfo.xx = new char[wcslen(yy)];
wcstombs(uinfo.xx, yy, strlen(uinfo.xx));
delete[] uinfo.xx;
You haven't initialised the memory that uinfo.xx points to so strlen(uinfo.xx) will keep going until it reaches a null byte, potentially off the end of the array.

Edit: also wcslen() counts characters (not bytes) so if there's even one single character that requires two MBCS-encoded bytes then you'll overflow the uinfo.xx buffer.

Standish fucked around with this message at 15:19 on Jan 29, 2009

Fehler
Dec 14, 2004

.
Thanks, I don't know what I was thinking when I wrote that.

So what would be the best way to convert wchar_t to char in C++?

I found "use_facet< ctype<wchar_t> >(loc).narrow(yy, yy+wcslen(yy), '?', uinfo.xx);" on Google, but that just causes the program to crash...

Edit - Here is my code:
code:
#include <iostream>
#include <exception>

using namespace std;

int main()
{
    wchar_t* xxx = L"abcdef";
    char* yyy;

	try {
		locale loc;
		yyy = new char[2];

		use_facet< ctype<wchar_t> >(loc).narrow(xxx, xxx+2, '?', yyy);
		cout << yyy << endl;
	} catch(exception& e) {
		cout << "EX: " << e.what() << endl;
	}

    return 0;
}
The output is just "EX: St8bad_cast".

Fehler fucked around with this message at 16:10 on Jan 29, 2009

Vanadium
Jan 8, 2005

Why are you messing around with dynamic memory :gonk:

Here is possibly useful code from a pal's hobby codebase:

code:
wstring Gosu::widen(const string& s)
{
#ifdef GOSU_IS_X
    setlocale(LC_ALL, "");
#endif

    size_t wideLen = std::mbstowcs(0, s.c_str(), 0);
    if (wideLen == static_cast<size_t>(-1))
        throw std::runtime_error("Could not convert from string to wstring: " + s);

    vector<wchar_t> buf(wideLen + 1);
    mbstowcs(&buf.front(), s.c_str(), buf.size());

    return wstring(buf.begin(), buf.end() - 1);
}

string Gosu::narrow(const wstring& ws)
{
    size_t narrowLen = std::wcstombs(0, ws.c_str(), 0);
    if (narrowLen == static_cast<size_t>(-1))
        throw std::runtime_error("Could not convert from wstring to string: " + string(ws.begin(), ws.end()));

    vector<char> buf(narrowLen + 1);
    wcstombs(&buf.front(), ws.c_str(), buf.size());

    return string(buf.begin(), buf.end() - 1);
}

mistermojo
Jul 3, 2004

I'm confused about using shell scripts. Say I want a shell script that will have a command line "startscan inputdirectory outputdirectory", and it will just copy files from one to another

How would I read that command line, and how would I work with it?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

mistermojo posted:

I'm confused about using shell scripts. Say I want a shell script that will have a command line "startscan inputdirectory outputdirectory", and it will just copy files from one to another

How would I read that command line, and how would I work with it?

What does this have to do with C/C++?

mistermojo
Jul 3, 2004

Avenging Dentist posted:

What does this have to do with C/C++?

i thought it used C? should I post this in another thread?

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

mistermojo posted:

i thought it used C? should I post this in another thread?

Shell scripts are written in shell, which has almost nothing whatsoever to do with C or C++. You should probably post your question in the Linux thread.

POKEMAN SAM
Jul 8, 2004

ShoulderDaemon posted:

Shell scripts are written in shell, which has almost nothing whatsoever to do with C or C++. You should probably post your question in the Linux thread.

What if you use the C shell (csh)?

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Ugg boots posted:

What if you use the C shell (csh)?

That was why I said "almost". It still belongs in the Linux thread, though.

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Today I spent most of my day trying to pin down a segfault caused by an fstream::write(). Stack traces say it's consistently caused inside the write() by a failed malloc(), which means (since I'm not running out of memory) it's probably a heap corruption issue. A double delete or a delete instead of delete[] or vice versa or something.

This is on a Solaris SPARC machine, so I had access to dbx, and with it the memleak checker and memory access reporting. In addition to using that for dynamic analysis, I've had the good old "step through the debugger and try to remember when poo poo's been freed."

I've been told there's also 'lint' or something like that for static analysis, but it doesn't seem to be on our dev machine. Or I'm not configured right, or something. But anyway. Have I missed any methods for tracking down memory corruption errors besides dbx, lint, and stepping?

(if this continues much longer I swear to god I'm just gonna start changing every raw pointer into a boost::shared_ptr and I am only half kidding here, today loving sucked)

Ciaphas fucked around with this message at 06:47 on Jan 30, 2009

sklnd
Nov 26, 2007

NOT A TRACTOR
valgrind, cppcheck

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Ugg boots posted:

What if you use the C shell (csh)?
To be fair, csh scripts aren't in C :)

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


A followup question to yesterday's analysis question. In my quest to track down this loving malloc-in-an-fstream error, I stumbled on libumem, which is an alternate memory library for Solaris SPARC (which is my target and development system). Apparently the idea is that it runs normally, except that it coredumps on various forms of heap corruption (like double deletes especially). And it's apparently usable in production, too, not just dev. So I decided to use LD_PRELOAD load libumem instead of the default library, to get it to dump a more useful core when it breaks.

The problem? It didn't break. The program finished execution, no signals, no errors, no coredumps, no nothing. And the output was exactly as expected. Stumped, I went back and reran the program without the LD_PRELOAD (so using the default allocator). Blam, blew up again.

I'm kind of at a loss as to what's happening here. Does this mean the default allocation library has a bug in it, and my code was never buggy at all? Or that, perhaps, libumem is hiding the problem for some reason, and that I still have a heap corruption somewhere? What's the likely scenario?

(I fully expect from well-learned pessimism that there is still a heap corruption going on and libumem is still masking it. But maybe there's hope yet.)

Ciaphas fucked around with this message at 18:23 on Jan 30, 2009

TSDK
Nov 24, 2003

I got a wooden uploading this one
I seem to remember reading that some SPARC implementations don't like calls to delete 0, or free( 0 ), even those are allowed according to the standard. So that's probably the first thing to check.

Second, a double-delete wouldn't be my first thought. If they're going to go, they usually (although not always) crash at the delete itself. A crash in a malloc is more often an indicator that an allocated buffer has been overrun, which means that any 'tags' used as headers and footers for allocations have been trashed just prior to the malloc that dies.

How large is the codebase we're talking about?

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


TSDK posted:

I seem to remember reading that some SPARC implementations don't like calls to delete 0, or free( 0 ), even those are allowed according to the standard. So that's probably the first thing to check.

Second, a double-delete wouldn't be my first thought. If they're going to go, they usually (although not always) crash at the delete itself. A crash in a malloc is more often an indicator that an allocated buffer has been overrun, which means that any 'tags' used as headers and footers for allocations have been trashed just prior to the malloc that dies.

How large is the codebase we're talking about?

Big enough that I spent the entire day yesterday combing for memory errors (and found a few) without finding the one that's causing the crash. Don't have a line count or anything like that handy (and in fact, while I'm on the internet here, I'm not at my work computer--security :argh: ), but at a guess call it about 40 classes of between 100 and 500 lines or so each getting executed in this particular run of the program (with heavy-duty amounts of looping), though I ended up checking the entire codebase by hand.

Not much help, I know, sorry.

Now that you mention it, though, I didn't test how libumem does on crashing when a buffer gets overrun, I only tested that it crashes on double deletes or deleting 0 (the default implementation doesn't crash on either). I'll have to check on that when I get back.

Ciaphas fucked around with this message at 19:03 on Jan 30, 2009

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
Really though, use valgrind

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Otto Skorzeny posted:

Really though, use valgrind

Not available on Solaris SPARC, or even Solaris x86 for that matter :(

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip

Ledneh posted:

Not available on Solaris SPARC, or even Solaris x86 for that matter :(

drat. A quick googling seems to indicate that on Solaris you can either spring for Purify(which by all accounts is very, very good on Solaris, much better than the Linux version of purify) or stick with umem and mdb.

TSDK
Nov 24, 2003

I got a wooden uploading this one

Ledneh posted:

Not available on Solaris SPARC, or even Solaris x86 for that matter :(
Have a look to see if you compiler will allow you to wrap functions (i.e. http://www.sourceware.org/ml/binutils/2000-09/msg00083.html).

Writing your own memory verification wrapper wouldn't actually take all that long. Probably about a day. You'd need a local std::map< void *, size_t > to keep track of all currently allocated buffers and their corresponding sizes (and a flag to suppress the custom allocation behaviour when you're adding to the internal map). When calling through to the __real_malloc, you allocate three times the normal size (or an appropriately large padding zone) and fill the buffer with a particular pattern before and after the actual pointer that you're returning.
code:
[CDCDCDCD CCCCCCC CCCCCCC CDCDCDCD]
 ^        ^
 |        |
 |        Fake alloc
 |
 Real alloc
Keep another std::map< void *, void * > so that you can map from the padded memory pointers that you're passing back to the app, and the real allocated pointers. When a free comes in, you can check to see if it's a current pointer, and then run through the padding bytes to check for any changes. Finally, strip through the buffer with a 'deleted' pattern (0xDDDDDDDD, or similar) and then call the real free.

A relatively simple scheme like that should pick up uninitialised memory, deleting invalid pointers, using pointers after they've been free'd, and corruption before and after a buffer.

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


I think that's what libumem already does in debug mode (except the pads are 0xdeadbeef and 0xbaddcafe, for some reason :pwn: ). But assuming libumem fails me, I'll try writing a wrapper like that. Pretty sure the compiler can handle that.

Speaking of which, I turned on more strict debug options in libumem and it found some more invalid deletes, so I'm waiting now for a recompile and rerun. We'll see if those were the ones or not, I guess.

Also, we might have Purify since we use ClearCase, but if we do it's not installed on our dev server. I'll bug our license guy when he gets back after the weekend, assuming I haven't solved this by then.


(EDIT) Think I found it--it ran through all the way but I have to test some more. There's a bit of code that looks something like this:

code:
// header
char* mRefreshBuffer;

// constructor
mRefreshBuffer = new char[mNumRefreshBytes];

// destructor
if (mRefreshBuffer != 0)
{
  delete[] mRefreshBuffer;
  mRefreshBuffer = 0;
}
Apparently, when the char array made was size 1, that was what was causing the buffer overrun--delete[] was overdoing it. I changed the destructor bit as follows:
code:
if (mRefreshBuffer != 0)
{
  if (mNumRefreshBytes == 1)
    delete mRefreshBuffer;
  else
    delete[] mRefreshBuffer;

  mRefreshBuffer = 0;
}
Now, correct me if I'm wrong, but I thought you were supposed to use delete[] on anything made with new[], even if the array size is 1. If that's true, does that mean the program ran this time due only to the power of Undefined Behavior(®)? And if that was false... then what the flipping gently caress is wrong with the Sun C++ compiler?! :mad:

Ciaphas fucked around with this message at 20:52 on Jan 30, 2009

Adbot
ADBOT LOVES YOU

TSDK
Nov 24, 2003

I got a wooden uploading this one

Ledneh posted:

Now, correct me if I'm wrong, but I thought you were supposed to use delete[] on anything made with new[], even if the array size is 1. If that's true, does that mean the program ran this time due only to the power of Undefined Behavior(®)? And if that was false... then what the flipping gently caress is wrong with the Sun C++ compiler?! :mad:
Yes, you're suppose to delete[] it, even if the array size is 1. Could well be a compiler bug then, although I usually like to dive into the actual asm generated and check it's doing something stupid before declaring that. Double check that elsewhere in the code there's nothing assuming mRefreshBuffer has more than one element.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply