Click here to Skip to main content
15,878,748 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello out there!

I have a problem with a class I use to enumerate Childwindows.
Every now and then i get "Stack around the variable 'String' was corrupted".
Usually this kind of message is triggered when you are "out of bounds" of some vector or array....but I can not find the error.

If someone here wants to test this class, here is the code:

#include "TChar.h"
#include "string.h"
#include "windows.h"
#include "Winuser.h"
#include <string>
#include <vector>

using namespace std;

typedef std::basic_string<TCHAR> tstring;              
                                                       

class ChildHandles
{

public:
    struct child_data 
    {
        tstring caption;
        HWND handle;
		tstring ClassName;
		RECT windowrect;
    };


private:
    std::vector<child_data> stuff;                     

    BOOL add_window(HWND hwnd) 
    {
        TCHAR String[300] = {0};
        if (!hwnd)
            return TRUE;                               
        if (!::IsWindowVisible(hwnd))
            return TRUE;                               
        LRESULT result = SendMessageW(hwnd, WM_GETTEXT, sizeof(String), (LPARAM)String);       
            return TRUE;                                
       
		child_data data;								

///////////////////////////////////////////////////////////////////////////////////
		
			for(int i = 0; i < sizeof(String)/8; i++)                 
            data.caption.push_back(String[i]);

///////////////////////////////////////////////////////////////////////////////////

		TCHAR buffer[30];
		GetClassName(hwnd,buffer,sizeof(buffer));
		for(int i = 0; i < sizeof(buffer)/4; i++)               
            data.ClassName.push_back(buffer[i]);
///////////////////////////////////////////////////////////////////////////////////		                              
		RECT childwindow;									
		RECT * pchildwindow;								
		pchildwindow  = &childwindow;						
		int checkmain = GetWindowRect(hwnd,pchildwindow);	
		if(checkmain=0)
        {
            // Error! Call GetLastError();
        }

///////////////////////////////////////////////////////////////////////////////////	

        data.handle = hwnd;                            
        stuff.push_back(data);                          
        return TRUE;
    }



    static BOOL CALLBACK EnumWindows(HWND hwnd, LPARAM lParam)
    {
        ChildHandles* ptr = reinterpret_cast<ChildHandles*>(lParam);
        return ptr->add_window(hwnd);
    }

public:
    ChildHandles& enum_windows(HWND hParentWnd) 
    {
        stuff.clear();                                  //clean up
        if(!EnumChildWindows(hParentWnd, EnumWindows, reinterpret_cast<LPARAM>(this)))
        {
            // Error! Call GetLastError();
        }
        return *this;
    }

    std::vector<child_data>& get_results() 
    {
        return stuff;
    }

};


Its called using:
std::vector<ChildHandles::child_data> ChildWindows = ChildHandles().enum_windows(htablehandle).get_results();


I am using Visual Studio.... Thanks for any hints, help or solutions...

:doh:
Posted
Comments
Andrew Brock 5-Feb-11 23:57pm    
You don't manually need to #include <winuser.h>
The file Windows.h includes WinUser.h

Also for files that don't belong to your solution you should use triangle braces < and > around the header name instead of double quotes:
#include "TChar.h"
#include <string.h>
#include <windows.h>
#include <winuser.h>
#include <string>
#include <vector>

If we format your code a bit better, we can see a few issues with it.
BOOL add_window(HWND hwnd) {
	TCHAR String[300] = {0};
	if (!hwnd) {
		return TRUE;
	}
	if (!::IsWindowVisible(hwnd)) {
		return TRUE;
	}
	//You should not use functions with W or A at the end unless you are specifically using that type of string. The macros will automatically choose the right function for your character set.
	LRESULT result = SendMessage(hwnd, WM_GETTEXT, ARRAYSIZE(String), (LPARAM)String); 
	//Check the return value of SendMessage. That is the number of chars written, not including the NULL. If it is more than 299 we have a problem
	if (result >= ARRAYSIZE(String)) {
		MessageBox(NULL, TEXT("Too many characters were copied into the buffer"), TEXT("Buffer overflow"), MB_OK); //You should insert a breakpoint on this line to see what is hapening if it gets hit.
	}
	return TRUE; //What is this? This will stop executing here and skip the rest of the function.
	child_data data;								
	///////////////////////////////////////////////////////////////////////////////////
	for(int i = 0; i < sizeof(String) / 8; i++) { //Be carefukl here... sizeof(String) = 2x the length of the string in String. Did you mean to use ARRAYSIZE()?
		data.caption.push_back(String[i]);
	}
	///////////////////////////////////////////////////////////////////////////////////
	TCHAR buffer[30];
	GetClassName(hwnd, buffer, ARRAYSIZE(buffer));
	for(int i = 0; i < sizeof(buffer) / 4; i++) { //Again, be carefukl here... sizeof(buffer) = 2x the length of the string in buffer. Did you mean to use ARRAYSIZE()?
		data.ClassName.push_back(buffer[i]);
	}
	///////////////////////////////////////////////////////////////////////////////////		                              
	RECT childwindow;
	//These 3 lines can br replaced with a single line
	//RECT *pchildwindow;
	//pchildwindow  = &childwindow;
	//int checkmain = GetWindowRect(hwnd, pchildwindow);
	int checkmain = GetWindowRect(hwnd, &childwindow);
	if (checkmain = 0) {
		//Error! Call GetLastError();
		//This doesn't tend to happen when you check hwnd != NULL && IsWindow(hwnd)
	}
	///////////////////////////////////////////////////////////////////////////////////	
	data.handle = hwnd;                            
	stuff.push_back(data);                          
	return TRUE;
}
 
Share this answer
 
v2
Comments
Espen Harlinn 6-Feb-11 5:44am    
Good work, thorough answer - 5+
replace: sizeof(String) by sizeof(String)/sizeof(String[0]). Unicode TCHAR has a size of 2 bytes.
 
Share this answer
 
Comments
stackhoover 5-Feb-11 12:50pm    
Ok sounds logical... Just tried it out. But I'm still getting: Run-Time Check Failure #2 - Stack around the variable 'String' was corrupted
stackhoover 5-Feb-11 12:53pm    
When debuging the compiler stops at:
--> stuff.push_back(data);
return TRUE;

;-(
mbue 5-Feb-11 16:00pm    
you have to do that for the call of GetClassName too. These functions need the count of characters in the buffer not the size of the buffer themselves. Run time errors can occur anywhere in your program they dont appear the next step of your code. this depends on usage of your heap.
regards.
To see if this is the line overwriting the stack,

LRESULT result = SendMessageW(hwnd, WM_GETTEXT, sizeof(String), (LPARAM)String);

Change it to this:

LRESULT result = SendMessageW(hwnd, WM_GETTEXT, 10, (LPARAM)String);
 
Share this answer
 
Comments
stackhoover 5-Feb-11 13:07pm    
Right now it works! But it usually does not happen right away...
If this is the error, what buffer size should I put in the place of "sizeof(String)" to make it work correct all the time? "10" is somewhat restrictive..... Regards SH
Steve Wellens 5-Feb-11 13:30pm    
Just make sure your buffer has enough room.

There's probable something a bit off with the TCHAR, Unicode, using SendMessageW (with the W) and the writing of the null terminator.

It probably only happens when the string returned is larger than your buffer.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900