|
What is inside the angle brackets of dynamic_cast? The html post stripped out this part - to stop this happening, click the "Display this message as-is (no HTML)" checkbox.
e.g. dynamic_cast<...>(val);
--
Andrew.
|
|
|
|
|
Done .
But I've since fixed the bug...
Swine
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
|
Ok, I'm not sure you've sorted this out, but here's my 2 cents.
The dynamic_cast actually has to examine the data at the other end of the pointer you feed it. It needs to look for the vtables of the type to which you want to cast the pointer. I'm guessing that the code inserted for the dynamic_cast doesn't do the dereference intelligently. So if you feed it a pointer that would normally dump core when you dereference it, it's still gonna yak.
The documentation should probably mention this, although perhaps the authors just assumed you'd be feeding it actual object pointers.
J
|
|
|
|
|
Yes, I would expect it to 'yak', but in a way that the catch(...) handler would just be invoked with an exception and everything should continue as normal, no? But it seems that a bad dynamic_cast<> also modifies memory somewhere, and really messes things up.
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
|
Another possible solution to your problem:
Use a map to track all valid handles in cService. When a handle is freed, remove the entry from the map. When a call is made which uses a handle, see if it exists in the map. If it does not, it is an invalid handle.
A numeric map should be pretty fast (just set the size of the hash table).
Just my 2 cents.
Matt Gullett
|
|
|
|
|
Actually that's exactly what I came up with after some more thought . But then I ran into a global / static object problem with this scheme. Check out my more Recent Post... I implemented the code as follows:
<br />
#pragma once<br />
<br />
#include "cMap.h"<br />
#include "cCriticalSection.h"<br />
<br />
<br />
class cParanoid : public cDestructible<br />
{<br />
public:<br />
cParanoid(void);<br />
virtual ~cParanoid(void);<br />
<br />
static cParanoid* GetParanoid(void* Pointer);<br />
<br />
private:<br />
static cMap<cParanoid*, cParanoid*, bool, bool> m_ParanoidMap;<br />
<br />
static cCriticalSection m_ParanoidSection;<br />
};<br />
<br />
cMap<cParanoid*, cParanoid*, bool, bool> cParanoid::m_ParanoidMap;<br />
<br />
cCriticalSection cParanoid::m_ParanoidSection;<br />
<br />
cParanoid::cParanoid(void)<br />
{<br />
m_ParanoidSection.Lock();<br />
{<br />
m_ParanoidMap[this] = true;<br />
}<br />
m_ParanoidSection.Unlock();<br />
}<br />
<br />
cParanoid::~cParanoid(void)<br />
{<br />
m_ParanoidSection.Lock();<br />
{<br />
if(!m_ParanoidMap.RemoveKey(this))<br />
{<br />
}<br />
}<br />
m_ParanoidSection.Unlock();<br />
}<br />
<br />
cParanoid* <br />
cParanoid::GetParanoid(void* Pointer)<br />
{<br />
cParanoid* Paranoid = NULL;<br />
<br />
m_ParanoidSection.Lock();<br />
{<br />
if(m_ParanoidMap.DoesKeyExist((cParanoid*)Pointer))<br />
{<br />
Pointer = (cParanoid*)Pointer;<br />
}<br />
}<br />
m_ParanoidSection.Unlock();<br />
<br />
return Paranoid;<br />
}<br />
The problem is that I get a pure virtual function called upon shutdown of the app. This is because CWinApp is a global, and the critical section and map of cParanoid get destoyed before CWinApp does, and there are some objects owned by CWinApp that are derived from cParanoid.
Any thoughts?
Thanks!
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
|
First thought,
if the objects owned by CWinApp are allocated on the heap (ie. new), then I would add a method to my CWinApp derived class something like "NotifyObjDelete(cParanoid* pValue)". In my CWinApp class, I would see if I own that object and set it to NULL.
I would call the NotifyObjectDelete from my objects destructor.
This is not a pretty solution, but might work depending on where you are in your development process.
I'll keep thinking.
Matt Gullett
(Sorry for the Anonymous, I am not at my PC right now.)
|
|
|
|
|
Thanks for the input... but unfortunately this won't do.
First off, the objects can't know anything about the CWinApp object, as they can be destroyed via a thread other than the main gui thread (and you're not supposed to access CWnd objects from other threads, and I believe this goes for CWinApp objects as well).
Second, the real nuts of the problem is that by the time the CWinApp destructor is invoked, the cParanoid static members have already been destroyed. This includes the critical section and the map of valid cParanoid pointers.
There's gotta be a way to specify which global objects get deleted in which order. I just don't know it...
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
|
Try adding code to your applications ExitInstance method to free the reference to these objects in your derived CWinApp object.
Tim Smith
Descartes Systems Sciences, Inc.
|
|
|
|
|
Now I wouldn't do this, but you might look into the #pragma init_seg pragma. This controls the order that objects are initialized. It would seem that it would also defined the order the are destroyed (reversed hopefully.)
Tim Smith
Descartes Systems Sciences, Inc.
|
|
|
|
|
This works great excluding one VERY minor point. There is a chance that a later created object could have the same address as one just freed. Thus a cUser object could be using an old pointer which just happens to match a new one. (I have no idea how rare this might be.)
We got around this problem by using an unique index system. Here is the basic layout.
1. Assume you have a table going from 1 to 4096 (4096 is just for example and the table size can grow if needed.) Each element of this table consists of the handle match value and a pointer to the real objects.
2. The handle is generated by taking the index in the table and oring it with a counter specific to that index. For example, let us say the handle was a DWORD. The low word is the index into the table. The high word is the unique counter for that index. Every time the index is allocated for an object, the unique counter is incremented. Thus, the first time index 20 is allocated, the handle would be 0x00010014. The next time it is allocated it would be 0x00020014. When a handle is allocated, the generated handle should be stored in the handle match value for that index.
3. When a handle is freed, it is placed at the end of a deleted list. Thus, all indexes are used prior to an index getting reused. This helps to make sure that a long period of time goes by before a handle is reused.
4. The table need not be a fixed size. If you start with 4096 entries and use all but 256 up, you can double the size of the table. There are two reasons to do this. First, you don't run out of indexes. Second, it helps to make sure handles don't get reused to quickly. If you had 4095 handles allocated and then allocated and freed the last one 65536 times quickly, it would reuse a handle quickly.
5. To look up an object from the handle. Take the handle and AND off the unquie counter. Locate the index in the object table. Compare the full handle against the handle match value for that index. If they do not match, then someone is using an old handle. If they do match, return the pointer.
6. This index system is actually faster than maps.
7. HOWEVER, 9 times out of 10 a map is a better solution because there is little worry about reusing the same object address as a handle.
(Hmm, maybe I should submit my handle to object class to CP.)
Tim Smith
Descartes Systems Sciences, Inc.
|
|
|
|
|
Very well thought out idea, Tim. Maybe you should indeed post the article. However, the handle reuse problem does not apply in my app, as I already thought of this before and avoided it in other ways... Hmmm, I'll look into that pragma you mentioned.
Cheers,
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
|
Yeah, the #pragma init_seg(lib) directive works just great! I know it's a bit of a hack, but it'll do quite well for now. All those nasty crashes are gone! I can't believe that I was having so much trouble just because of a stupid dynamic_cast<>!
cheers,
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
|
Hmmm looks like I am gonna have to implement this for one of my classes! I think I am having the handle reuse problem, though in a different module...
I will try to follow your suggestions, and see how it goes.
Thanks!
swine
[b]yte your digital photos with [ae]phid [p]hotokeeper - www.aephid.com.
|
|
|
|
|
does Win98 interpret a WM_KEYDOWN message differently than in WinNT ?
I have a method that extract a bunch of keyboard data whenever the WM_KEYDOWN is hit
It pulls off stuff like the virtual key code, the char representation, etc. On NT this works fine (and is my primary dev platform). But when I run it on 98 I get nothing! For example the VK codes that I get on NT turn to nothing on 98. Is there something special you have to do to properly handle this ?
|
|
|
|
|
From my experience this should be the same except some bizarre key combinations such as Shift + (keypad +,-).
|
|
|
|
|
I don't know if this is the appropriate forum to be asking this question, but i'll assume as VC++ programmers someone will know, because it's probably VC++ programmers who write the code for the JScript interpreter.
Do the following code optimizations apply to both compiled and interpreted code.
Common sub-expression elimination
Loop invariant hoisting
Dead store elimination which i'll assume is dropping unused functions...?
I gave this some thought and i figure if it works for compiled why shouldn't it work in scripts...? Do you think the JScript interpreter does this while reading the file into it's buffer...? dead store is obvious...less text, less size = quicker downloads. You get size opt, but wouldn't this make a difference with execution time as well...?
Merci buckets...
Tia
"An expert is someone who has made all the mistakes in thier field" - Niels Bohr
|
|
|
|
|
I don't know this for certain but I would be very surprised if any significant code optimization is done by the JS compiler. Speed of compilation is generally a higher priority than speed of execution.
|
|
|
|
|
Really...i would figure both would be about equal for scripting langs. Maybe even in favour for run time, seeing how people kinda expect to have a short delay in the download process.
I'm really curious if optimized code would work in a interpreted environment.
Take the following example:
for(i=0; i<10000; i++)
a[i] = b + c;
t = a + b;
for(i=0; i<10000; i++)
a[i] = t;
even in interpretation it one less operation to perform each iteration of the loop...?
I figure i'll try it out by executing similar loops and timing the diff. Only i don't know quite how to go about it. Would JScript allow me to clock it in the code itself or will i have to do it through the IWebBrowser2 or similar component
Minus 30 degrees C is so damn cold
"An expert is someone who has made all the mistakes in thier field" - Niels Bohr
|
|
|
|
|
If the "interpreter" is actually a JIT compiler, then it can do all those optimizations, but a true interpreter would be limited to statement-level common subexpression elimination.
|
|
|
|
|
I think I have a fairly broken class. I try to locate the Access Violation but I just can't seem to find it. I've tried examing the call stack but all i get is a bunch of kernel addresses. Can someone check it out and tell if there is anything wrong?
Here is the .h file
#ifndef _KTRANSCEIVER_H_
#define _KTRANSCEIVER_H_
#pragma warning(disable: 4786)
#include "bfThread.h"
#include "kStreamServer.h"
#include <vector>
#define EOK 0x0F1
#define EBADSOCK 0x0F2
using std::vector;
class bfSocket;
class kTransceiver:public bfThread
{
private:
struct client_t
{
bfSocket* pSock;
client_info *clinfo;
};
vector< bfSocket* > m_pClients;
bfSocket* m_pSource;
string m_streamName;
source_info *info;
//Removes a client from list of clients
int cleanClients();
int removeClient(std::vector<bfSocket*>::iterator sock_i);
int removeAll();
void End();
protected:
public:
//Constructor
kTransceiver(bfSocket* pSource, source_info *_info);
~kTransceiver();
//Add a client to list of clients
int addClient(bfSocket* pClient, client_info *clinfo);
DWORD ThreadProc();
};
#endif
Here is the .cpp file
#pragma warning(disable:4786)
#include <vector>
#include <string>
#include "../include/kTransceiver.h"
#include "../include/bfSocket.h"
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
kTransceiver::kTransceiver(bfSocket *pSource, source_info *_info)
{
if (pSource)
m_pSource = pSource;
else
m_pSource = NULL;
info = _info;
}
kTransceiver::~kTransceiver()
{
End();
}
int kTransceiver::addClient(bfSocket* pClient, client_info *clinfo)
{
string buffer;
string temp;
if (pClient && pClient->IsConnected())
{
//Client Greeting
if (clinfo->icy_metdata) //client uses icy
{
buffer = "ICY 200 OK\r\n";
buffer += "Icy-Name: ";
buffer += info->name;
buffer += "\r\n";
buffer += "Icy-Notice1:This must be a Winamp <www.winamp.com> compatible player.\r\n";
buffer += "Icy-Notice2:Katie Alpha 0.1\r\n\r\n";
}
else
{
//Send audiocast headers
buffer = "HTTP/1.0 200 OK\r\n";
buffer += "x-audiocast-name: ";
buffer += info->name;
buffer += "\r\n";
if (!info->description.empty())
{
buffer += "x-audiocast-description:";
buffer += info->description;
buffer += "\r\n";
}
if (!info->genre.empty())
{
buffer += "x-audiocast-genre: ";
buffer += info->genre;
buffer += "\r\n";
}
buffer +="\r\n\r\n";
}
pClient->Send(buffer, buffer.length());
//Add to list
BeginLock();
m_pClients.push_back(pClient);
EndLock();
}
else
{
if (pClient)
delete pClient;
return EBADSOCK;
}
return EOK;
}
int kTransceiver::removeClient(std::vector< bfSocket* >::iterator sock_i)
{
BeginLock();
delete *sock_i;
*sock_i = NULL;
m_pClients.erase(sock_i);
EndLock();
return EOK;
}
DWORD kTransceiver::ThreadProc()
{
string buffer;
std::vector<bfSocket*>::iterator i;
int read, sent, total, z;
BOOL tryagain = FALSE;
while(isRunning())
{
read = 0;
sent = 0;
//read from the source
read = m_pSource->Receive(buffer, 2046);
if (!m_pSource->IsConnected())
{
break;
}
//Send the data to the clients
BeginLock();
printf("Checking size: %d\n", m_pClients.size());
printf("Sending data...\n");
for (i = m_pClients.begin(); i != m_pClients.end(); i++)
{
if(m_pClients.size() > 0)//make sure there are clients to send the data to
{
total = 0;
tryagain = FALSE;
//try twice to write
for (z = 0; z < 2; z++)
{
while (total < read) //make sure that it all gets sent
{
sent = ((bfSocket*)*i)->Send(buffer, read);
if (sent <0)
{
printf("Unable to send data! Trying again...\n");
tryagain = TRUE;
break;
}
total += sent;
if (!((bfSocket*)*i)->IsConnected())
{
printf("Client %s disconnected.\n", ((bfSocket*)*i)->GetAddress());
tryagain=FALSE;
break;
}//if
}//while(sent < read)
if (tryagain)
{
Sleep(100);
}
else
break;
}//for
}
else
break;//if
}//for
cleanClients();
EndLock();
Sleep(100);
}//while(isRunning())
//destroy our source
delete m_pSource;
delete info;
removeAll();
return 0;
}
void kTransceiver::End()
{
bfThread::End();
}
int kTransceiver::removeAll()
{
std::vector<bfSocket*>::iterator i;
if (m_pClients.size() == 0)
return EOK;
for(i = m_pClients.begin(); i != m_pClients.end(); i++)
{
//disconnect the client
((bfSocket*)*i)->Disconnect();
//remove the socket
delete ((bfSocket*)*i);
}
return EOK;
}
int kTransceiver::cleanClients()
{
std::vector<bfSocket*>::iterator i;
BOOL bKeepChecking = FALSE;
printf("Cleaning Clients...\n");
if (m_pClients.size() == 0)
return EOK;
for (i = m_pClients.begin(); i != m_pClients.end(); i++)
{
//check if the client is disconnected
if (*i)
{
if (!((bfSocket*)*i)->IsConnected())
{
//client isn't connected so remove him
printf("Removing Client.\n");
removeClient(i);
bKeepChecking = TRUE;
break;
}
}
}
if (bKeepChecking)
cleanClients();
return EOK;
}
<b>S</b>tephen <b>C</b>aldwell
Blackfission, CEO
http://blackfission.myip.org:81
|
|
|
|
|
Hey Stephen,
It's hard to tell what's happening just by looking at your code. We don't know what any of the data member types are, and of course we can't compile it. Are you getting the crash in Debug mode? You should also try setting the Access Violation Exception to Stop Always, which should tell you exactly where the crash is happening (this can be done by running the app, then in VC going Debug | Exceptions | and then setting the Access Violation to Stop Always).
Hope this helps!
cheers,
swinefeaster
Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
|
|
|
|
|
When I try to edit the HOSTS file to get a name on my server so my client apps can connect to the server app by typing xblade.focus.com instead of the damn IP number (xxx.xxx.xxx.xxx). But it seems to not work for me! :/
I've tried typing:
127.0.0.1 xblade.focus.com
and
#xxx.xxx.xxx.xxx is my IP to the computer (server, but a client in my LAN)
xxx.xxx.xxx.xxx xblade.focus.com
I've restarted the system after changing it, but nothing happens. My network can be unstable or not work correctly, so can that be the errror?
The error code is 10061 (No connection could be made because the target machine actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host—that is, one with no server application running.)
HELP!!
------------------------------
©0d3 ©®4©k3® - That's me!
------------------------------
|
|
|
|
|
I have talked with a lot of programmers about this (including one professor) and all know it's possible, but no one knows exactly how I can do this. I hope you do.
ifstream MyFile(FileName);
while (!MyFile.eof()) {
MyFile >> MyString;
cout << MyString << endl; }
This works great, but one problem is that the default >> operator seperates these words at spaces so I get from "What!! is, this;thing man?" :
What!!
is,
this;thing
man?
(4 words)
I want to separate at all punct char's (\":;?!, etc) so I get:
What
is
this
thing
man
(5 words)
Does anyone have an idea -- a lot of people in my lab are interested. We think that we can overload the << operator to do this, but need some guidance.
Thanks,
Tim
(oh how easy this is to do in Perl . . . )
---------------------------------------
Tim Booher
|
|
|
|
|
Read in a line at a time (getline, I think) and then break up the string using strtok(). Keep a running count of how many tokens you get for each line. You can use multiple string delimiters with strtok(). Look it up in the MSDN documentation.
Jon Sagara
What about ?
|
|
|
|