|
Well I tried what you suggested, but Windows doesn't seem to want to call my OnGetMinMaxInfo()
I've got a CVideoView, which is derived from CPlaybackView, which is derived from - you guessed it - CView.
here's what I've got in CVideoView:
...
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI );
...
DECLARE_MESSAGE_MAP()
...
ON_WM_SIZE()
ON_WM_GETMINMAXINFO()
...
ENDMESSAGEMAP()
...
...
void CVideoView::OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI )
{
TRACE( "In CVideoView::OnGetMinMaxInfo()" );
lpMMI->ptMinTrackSize.x = CXVHC+CXMARGIN*2;
lpMMI->ptMinTrackSize.y = CYVHC+CXMARGIN*3;
}
That TRACE() never prints
As you might have noticed, I commented out my overridden WM_WINDOWPOSCHANGING, cos I thought that might be why OnGetMinMaxInfo() wasn't being called. But it makes no difference.
I'm wondering what brain-dead mistake I've made
|
|
|
|
|
Try placing the code in your frame class instead of your view class.
|
|
|
|
|
Great!
That's fixed it. It's working just right now.
Thanks a lot for all your help guys, today was an enjoyable day in school
Pete
|
|
|
|
|
I am sorry about misguiding you to use the view class, my mind was on one of the earlier questions that related to painting through the view class.
I am glad that you solved your problem though.
kilowatt
Checkout my Guide to Win32 Paint for Intermediates
|
|
|
|
|
No problem, you set me on the right track, which was more important. Plus I learned some more about how windows deals with resizing, painting etc.
I appreciate it
|
|
|
|
|
OK I have a program (console app) that gets connected to via sockets from another machine and then it just gets sent data repeatedly (financial data feeds). The program has to run 24/7, but on the multi processor box (Winnt4 sp5 dual Intel) it always crashes. The longest I have gotten it to run so far is about 12 hours. When the program runs on Winnt4 Server with a single processor it seems to work better (at least no crashes). Ditto with Windows 2K Worstation.
Are there special libs you need to link with or provide when running on a multi processor box ? I have never done anything like this so forgive what may be a stupid question
The program is a multi-threaded program, running in release mode
|
|
|
|
|
Quick fix - use the /ONECPU switch in the boot.ini file!
But seriously folks...
The conventional wisdom is that you haven't tested your multithreaded app until you've tested it on a multi-processor machine.
The HAL and ntoskrnl _are_ different for multiple cpu boxes, but nothing else AFAIK.
Sounds like a fun one. (Feel free to vent at me for that )
|
|
|
|
|
Tim Deveaux wrote:
Feel free to vent at me for that
Nah!
I kind of figured this would be the case...sigh...
I wish I knew where to look though, maybe we'll just say that our software only runs on single processor machines , yeah that's the ticket, and you can only run our program, yeah, and then ....
Grrr...back to pulling out my hair
|
|
|
|
|
I _think_ the main area to look at is data access.
On a single CPU, threads are switched in a 'more' serialized fashion - while one might be preempted before finishing what its tweaking, it doesn't need to worry about some other identical code running concurrently on another processor - so I guess I'd look at shared data sections etc.
But, yes, pulling hair is good. Assuming you have some to spare. Not all of us do...
|
|
|
|
|
by shared data do you mean stuff like the lists that the various threads work with and share ? On my app I have a singleton application class that contains a set of lists. The threads have access to the lists - write access is protected by using mutexs.
|
|
|
|
|
What about read access? If someone is reading, you can't have anybody else write.
Also, if your shared data isn't shared over multiple processes and your locks will be very shortlived, then use a CRITICAL_SECTION and not a mutex. A CS performs much better.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
I'll double check this. Thanks
|
|
|
|
|
Jim Crafton wrote:
I kind of figured this would be the case...sigh...
Incorrect software development strikes again!
FWIW, tracking things like this down are really not that hard. It was already said that you should look at shared memory locations (shared variables), but you then should extend that search to code in and around Critical Sections, and code near InterlockedIncrement(...) and InterlockedDecrement(...).
IME, those locations are the best place to find mistakes (or misunderstandings).
Jim Crafton also wrote:
maybe we'll just say that our software only runs on single processor machines[...]
A very dirty thing you can do is to launch the app with a little helper application that uses CreateProcess(...) to launch your application with the CREATE_SUSPENDED flag, and you can then use the SetProcessAffinityMask(...) function to force the thing to run on one CPU. Note that this is not a fix, nor is it The Right Thing to do, but it should work...!
Peace!
-=- James.
|
|
|
|
|
maybe we'll just say that our software only runs on single processor machines
I hope you'll never need it, but if you can't find the bug(s) you could limit the process to one CPU using SetProcessAffinityMask.
|
|
|
|
|
Mike Nordell wrote:
I hope you'll never need it, but if you can't find the bug(s) you could limit the process to one CPU using SetProcessAffinityMask.
Must be a delayed echo...
Peace!
-=- James.
|
|
|
|
|
Somewhere you have some data that is being shared between two threads in your application. This memory is not being properly locked for access. Anytime you modify/read memory shared by multiple threads, you have to serialize access by some type of lock. (CRITICAL_SECTION works great)
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
would this result in crashes that seem to always result in an access violation in either the free() code ( it is deep in the MS heap allocator code) or new() ?
Tim Smith wrote:
Anytime you modify/read memory shared by multiple threads, you have to serialize access by some type of lock.
Yeah, I am doing this using mutexes there is a mutex for each list that I have (there are 3). Would CRITICAL_SECTION's be better ?
|
|
|
|
|
Generally, critical sections are better excluding 2 cases.
1. If the lock has to be shared between multiple processes.
2. If the lock is a long term lock where there will be a high occurrence of one thread having to wait for another thread to finish.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
Jim Crafton wrote:
would this result in crashes that seem to always result in an access violation in either the free() code ( it is deep in the MS heap allocator code) or new() ?
IME, that is due to heap corruption, which is often caused by writing off the end of an allocated block of memory. Doing a double-free or a double-delete can also cause that problem.
Are multiple threads constantly allocating memory, passing the pointer(s) around, and then trying to free that memory? Misusing dynamically allocated memory is bad in the first place, but doing it in an MT application using the normal heap is a big no-no.
Peace!
-=- James.
|
|
|
|
|
Yes - if this is bad what are my options ?
Thanks !
|
|
|
|
|
Jim Crafton wrote:
Yes - if this is bad what are my options ?
If what is bad? Which portion of my message are you referring to? Options? Well, you can send your code to me (we will do an NDA beforehand, of course), and I will help you with it for the special reduced rate of US$125/hr! But barring that...
If you think that memory is being stepped on (or off of the end of) or otherwise mishanded, a debug build should quickly find that problem.
If a debug build is not an option, you may also be able to introduce code into the program to help track down where the problem is. For example, if your threads are allocating and deallocating proper objects (as opposed to simple types like char , int , double , etc.), you can do something like adding a bool member variable to the class that is set to true in the object's constructor and false in the destructor. If the destructor first tests to make sure that the member variable is true before setting it to false , you will be able to find a double-delete.
Adding "buffer variables" before and after the existing member variables can be used to detect memory overwrites. For example, make the buffer variables a set of 4 DWORD s, and place a set before and after the other member variables. In the constructor, fill the buffer variables with a known value (like 0x2468BEEF ). In the destructor, verify that the buffer variables all still equal the same value they were initialized to.
HTH
Peace!
-=- James.
|
|
|
|
|
Jim-
This is the kind of bug everyone dreads. But take heart, at least your crash is reproducable.
Do you know which line of code is failing ? You need MAP files and preferably have had Drwatson running when the program crashed.
Next time u get a chance, run DrWatson32 (from the winnt/system32 directory) and wait for the crash, then open the Drwtsn32.log file ( I forgot where this file is created, but u can search for it)
Check out http://support.microsoft.com/default.aspx?scid=kb;EN-US;q275481 for more detail
-
V
|
|
|
|
|
Hello,
I am using a STL multimap object to store keys and values.
The key are of type CPosition and values are of type CBirds*
class CPosition consists of two integers X and Y
class CPosition
{
public:
int X;
int Y;
};
To sort the keys I used something like:
struct lesscpos
{
bool operator () (const CPosition& Pos1, const CPosition& Pos2) const
{
if (Pos1.X < Pos2.X)
return true;
else if (Pos1.X > Pos2.Y)
return false;
else if (Pos1.Y < Pos2.Y)
return true;
else
return false;
}
};
I declare the multimap object like this:
multimap <CPostion, CBirds*, lesscpos> MyMap;
My program complies fine. The problem is when I use the count member function to determine how many values share the same key. It seems to me it is going into an infinite loop.
CPosition pos (i, j);
int x = MyMap.count (pos);
It hangs when it finds more than one value with the same key in the following function:
template<class _BidIt,
class _Diff> inline
void _Distance2(_BidIt _First, _BidIt _Last, _Diff& _Off,
bidirectional_iterator_tag)
{ // add to _Off distance between bidirectional iterators (redundant)
for (; _First != _Last; ++_First)
++_Off;
}
Can anyone help me with this one?
Thanks a lot
Best regards,
Alexandru Savescu
|
|
|
|
|
have you tried using map::lower_bound and map::upper_bound and then iterate through the results manually to see what is going on ?
also are i,j "valid" values ?
just guessing - don't know if this will help
|
|
|
|
|
I found my problem. It was the comparison function. It looks that it should strictly sort the keys, not just partially sort them.
It does not matter if i, j are invalid because in this case the count function will return 0 (that's what MSDN says).
Best regards,
Alexandru Savescu
|
|
|
|