Jump to content
  • Advertisement
Sign in to follow this  
etsuja

unknown cause of exception

This topic is 4412 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm having a problem with one of my functions causing an exception but I can't figure out why. I've narrowed it down to one line in the function that calls another function so I'm not sure if the error is in the calling function or the function called.. this only happens when I run it straight from the folder and not within visual C 8. It also has different behavior when I run it straight from the folder but I don't know why.
void SerialGen()
{ 
	char alpha[80] ="ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
	char* ppasswrd = NULL;
	wchar_t* wppasswrd = new wchar_t[11];
	char passwrd[80]="";
		
	int numChars = 20;
	
	for (int n=0; n<numChars; n++)
	{
		int x;
		x = 0 + int(35.0 * rand()/(RAND_MAX+1.0));
		passwrd[n]= alpha[x];
	}
	
	ppasswrd = passwrd;

	memset(wppasswrd,0,sizeof(wppasswrd));

	MultiByteToWideChar(  CP_ACP, NULL,ppasswrd, -1, wppasswrd,numChars );

	AddString(wppasswrd); // this is the line that causes an exception

	getchar();
	wppasswrd = NULL;
	delete[] wppasswrd;

}



here's the funtion called which works fine with passing TEXT("blah") to it but I don't know if it's causing the above problem when passing the wchar_t pointer.
STRINGSTRUCT* AddString(LPCWSTR StringToAdd)
{
	if(FirstString == NULL)
	{
		FirstString = new STRINGSTRUCT;
		LastString = FirstString;

		LastString->Next = NULL;
	}
	else
	{
		LastString->Next = new STRINGSTRUCT;

		LastString = LastString->Next;
		LastString->Next = NULL;
	}

	size_t len;

	LastString->DisplayString = StringToAdd;
	StringCchLength(StringToAdd, 512, &len);

	LastString->StringLength = len;

	return LastString;
}



can anyone help me out?

Share this post


Link to post
Share on other sites
Advertisement
Looks like your wchar_t string is overwriting the boundary... one line BEFORE you say.

Your wchar_t array should at least be the same size as the password... and you're only allocating 11 for it.

Share this post


Link to post
Share on other sites
well I was only allocating 11 for it cause it's 2 bytes and the password is only 20 chars long of 1 byte. for some reason if I make the wppasswrd anything other than 11 or 12 I get extra blank characters printed on screen with my password generated.

Share this post


Link to post
Share on other sites
Quote:
Original post by etsuja
well I was only allocating 11 for it cause it's 2 bytes and the password is only 20 chars long of 1 byte. for some reason if I make the wppasswrd anything other than 11 or 12 I get extra blank characters printed on screen with my password generated.


you need wchar_t[20] or larger... because MultiByteToWideChar() will write 20 wchar_t's into the array, which is 40 bytes.

You should probably make the array 21 wide chars long, and use ZeroMemory or memset to clear it first, too.


void SerialGen()
{
char alpha[80] ="ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
char* ppasswrd = NULL;
wchar_t* wppasswrd = new wchar_t[21];

char passwrd[80]="";

int numChars = 20;

for (int n=0; n<numChars; n++)
{
int x;
x = 0 + int(35.0 * rand()/(RAND_MAX+1.0));
passwrd[n]= alpha[x];
}

ppasswrd = passwrd;

memset(wppasswrd,0,sizeof(wppasswrd));

MultiByteToWideChar( CP_ACP, NULL,ppasswrd, -1, wppasswrd,numChars );

AddString(wppasswrd); // this is the line that causes an exception

getchar();

// whoa! and the following will leak memory
// wppasswrd = NULL;
// delete[] wppasswrd;

// do this instead

delete[] wppasswrd;
wppasswrd = NULL;

}

Share this post


Link to post
Share on other sites
I set the length to 21 and I tried using zeromemory and memset but it prints the password with this after it when running from VC8 |||||||| and ||| when running from the folder. And I don't think I can use delete[] on it cause it clears the password. I don't know where I can deallocate it unless I make it global. maybe I could return it and then delete it outside the function? When it's 21 I don't get that exception though.

EDIT: nevermind I just figured out why it was doint it I changed
MultiByteToWideChar( CP_ACP, NULL,ppasswrd, -1, wppasswrd,numChars )
to
MultiByteToWideChar( CP_ACP, NULL,ppasswrd, -1, wppasswrd,(numChars + 1) )

Share this post


Link to post
Share on other sites
Quote:
Original post by etsuja
I set the length to 21 and I tried using zeromemory and memset but it prints the password with this after it when running from VC8 |||||||| and ||| when running from the folder. And I don't think I can use delete[] on it cause it clears the password. I don't know where I can deallocate it unless I make it global. maybe I could return it and then delete it outside the function? When it's 21 I don't get that exception though.


memset(wppasswrd,0,sizeof(wchar_t) * 21);

And if you don't want to clear the password... then don't delete wppassword
[smile]

Just remember to delete the array somewhere... keep a pointer to the wchar_t array in your struct, or something, and then delete it when your STRINGSTRUCT is deleted... perhaps in the destructor.

Share this post


Link to post
Share on other sites
wait if DisplayString in my struct = StringToAdd and wppasswrd is getting passed to AddString isn't it already getting deleted when I delete my struct?

Share this post


Link to post
Share on other sites
Quote:
Original post by etsuja
wait if DisplayString in my struct = StringToAdd and wppasswrd is getting passed to AddString isn't it already getting deleted when I delete my struct?


Not unless you have explicit code in your struct's destructor to take care of those. You'll have memory leaks unless you call "delete" for everything you've called "new" for, and "delete[]" for everything you've called "new[]" for.



// delete FirstString calls...

STRINGSTRUCT::~STRINGSTRUCT()
{
// you have to iterate through your linked list, and delete
// all "DisplayString" like this

// delete[] Next->DisplayString;

// THEN You have to iterate through, deleting all "Next"... which might
// blow the stack, if your linked list is very long (delete Next; would
// recursively call the destructor STRINGSTRUCT::~STRINGSTRUCT())
}


This is where smart pointers can really help you... with the "Next" pointers. If you declared "Next" a smart pointer in your struct, instead of just "STRINGSTRUCT *Next", it would mean you'd only have to explicitly go through and delete[] Next->DisplayString.

You'd no longer have to call "delete Next" in the destructor, and potentially blow the stack with a long linked list.

boost::shared_ptr and Loki::SmartPtr are good places to start.

Share this post


Link to post
Share on other sites
Well I tried this and got an assertion failure:


void DeleteAllStrings()
{
STRINGSTRUCT* ThisString = FirstString;
STRINGSTRUCT* DeadString = NULL;

while(ThisString != NULL)
{
DeadString = ThisString;
delete[] DeadString->DisplayString;
ThisString = ThisString->Next;
delete DeadString;
}
FirstString = NULL;
LastString = NULL;
}




I also tried regular delete too

Share this post


Link to post
Share on other sites
That code looks fine (to me)

When does it assert? Have you single-stepped through?

Does it assert on the first delete[], the first delete, or after everything is deleted?

Are there any other deletes or delete[]s in your code?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!