|
Hey guys
I am playing with ATL as you know. I have a weird problem.
I am testing my ATL stuff using VB/ASP
The problem is that when I was using VB, I find that later when I rebuild my component from VC++ I get this error saying the file cannot be opened for writing.
What I then used to do was to close VB and then rebuild it with no probs. This was an annoyance in a way.
But now its worse. I jus tried it out from ASP and it worked. I was happy too. Now I make a small change and want to rebuild it. I get the cannot open dll error. I closed the IE instance and get the same error.
Now what do I do?
Do I have to restart my machine each time?
I believe the reason for this is that ASP/VB fails to decrement the reference count.
How do I force them to do that?
Nish
It's seven o'clock
On the dot
I'm in my drop top
Cruisin' the streets - Oh yeah
I got a real pretty, pretty little thing that's waiting for me
|
|
|
|
|
Damnation!
I am going to reboot now (
Bye for 5 minutes.
I'll be back...
Nish
It's seven o'clock
On the dot
I'm in my drop top
Cruisin' the streets - Oh yeah
I got a real pretty, pretty little thing that's waiting for me
|
|
|
|
|
Here is the erring code by the way :-
<%
Dim x
Set x = CreateObject("SIMPLEINIEDIT.IniEdit")
Response.Write x.GetPrivateProfileString("nish", "abc", "c:\xyz.ini") & "<br>"
Dim y
y = x.GetNiceArray()
For Each j In y
Response.Write j & "<br>"
Next
Response.Write x.TestMethod()
Set x = Nothing
%>
It's seven o'clock
On the dot
I'm in my drop top
Cruisin' the streets - Oh yeah
I got a real pretty, pretty little thing that's waiting for me
|
|
|
|
|
I would say restart the IIS Web Service. IIS is loading the instance of your DLL and locking the file.
Kelly Herald
Software Developer
Micronpc, LLC
|
|
|
|
|
Kelly Herald wrote:
I would say restart the IIS Web Service. IIS is loading the instance of your DLL and locking the file.
Okay, that's possible too.
But still it's an annoyance.
I thought IIS would that, the component is no longer in use and would call Release()
Nish
It's seven o'clock
On the dot
I'm in my drop top
Cruisin' the streets - Oh yeah
I got a real pretty, pretty little thing that's waiting for me
|
|
|
|
|
Are you juggling with the reference count, I mean addref'ing in order to hand out pointers to a function call or something. It sounds like all of your objects are not releasing, and this would force you DLL to remain mapped into memory. That would lock the file and keep it from being updated when you compile.
When you test it in VB, you are running it in the VB run-time process space, so when you kill the debugger (VB runtime), it forces the DLL to be unloaded whether all of the COM objects were successfully released or not.
|
|
|
|
|
kilowatt wrote:
Are you juggling with the reference count, I mean addref'ing in order to hand out pointers to a function call or something.
From my component I am not touching AddRef() or Release() and if I do it's ATL, not me
kilowatt wrote:
When you test it in VB, you are running it in the VB run-time process space, so when you kill the debugger (VB runtime), it forces the DLL to be unloaded whether all of the COM objects were successfully released or not
Yes. But then I am expecting IIS to do the same for me
Nish
It's seven o'clock
On the dot
I'm in my drop top
Cruisin' the streets - Oh yeah
I got a real pretty, pretty little thing that's waiting for me
|
|
|
|
|
It also depends on how IIS is loading your DLL.
If your DLL is loaded as an INPROC_HANDLER, then IIS will not try to unload the DLL.
|
|
|
|
|
kilowatt wrote:
If your DLL is loaded as an INPROC_HANDLER, then IIS will not try to unload the DLL.
Oh! Any way I can force IIS to do it in a way, where it would Release() ?
Nish
It's seven o'clock
On the dot
I'm in my drop top
Cruisin' the streets - Oh yeah
I got a real pretty, pretty little thing that's waiting for me
|
|
|
|
|
I'm not sure but I think one solution for it is change your Threading Model
Mazy
"So,so you think you can tell,
Heaven from Hell,
Blue skies from pain,...
How I wish,how I wish you were here." Wish You Were Here-Pink Floyd-1975
|
|
|
|
|
The DLL is loaded by the COM environment ( when IIS will call CoCreateInstance). IIS do some kind of object pooling to optimize the response for your ASP page, so eventually your object will be released when the timeout for the object will expire. If you want to track the addref / release / QI for your object compile the debug version of your component and define _ATL_DEBUG_QI, _ATL_DEBUG_REFCOUNT & co, start a program which catch the debug output ( as DbgView from sysinternals or dbgmon from Platform SDK ), load your web page and keep an eye on the debug output.
|
|
|
|
|
I've experienced this too. I think IIS deliberately holds the ref count up to stop the object unloading. This way, ASP experiences faster application startup.
Sorry to dissapoint you all with my lack of a witty or poignant signature.
|
|
|
|
|
Can anyone tell me when I call data(), the const char * that gets returned, is it safe after the string goes out of scope ? If not, how do I get access to the buffer of a string without having to create a new char * and doing a strcpy ???
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
calling c_str() and data() both return pointers to the internal data. So if the basic_string goes out of scope, these pointers will be invalid.
If you want a copy of the data use copy(), which I guess you will still have to allocate a buffer for this as well.
|
|
|
|
|
I was hoping to get out of creating the pointer, if I could. But this is what I have done instead, so thanks for the advice.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
Maybe you should just copy the contents to another std::string? The cost will not be greater than new/strcpy, and may be less if your STL uses copy-on-write.
Tomasz Sowinski -- http://www.shooltz.com
|
|
|
|
|
This question, like the other one I asked this afternoon, was motived by my having to write code to fit into interfaces provided for me. Returning anything other than a char * was not an option for me. In the end I did it the weasel way and created new char * to hold the final string. I'm guessing that was the intent of the std library designers neglecting to provide such a function.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
If I have a vector, of CStrings for example, and I am stepping through the vector in a loop, like this:
StringVector::iterator it = aHeadComponents.begin();
StringVector::iterator end = aHeadComponents.end();
for(; it != end; ++it)
now inside the loop I need to pass each string to a function that takes a CString pointer, what do I do ? I know I can dereference the iterator to get a CString, but I was under the impression that what I have should *not* be considered a CString pointer ? Is this wrong ? Am I worrying about nothing ? Please help....
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
Can't a vector hold CString pointers? Then just pass the pointers from dereferencing the iterator? Or you could try the way you have it now, declare a CString str just to hold the string from the vector on each loop passing the pointer till the end.
Or am I way off base Christian? lol I'm no pro with STL yet, but hopefully I gave you some ideas.
Cheers
|
|
|
|
|
Jay Beckert wrote:
Can't a vector hold CString pointers? Then just pass the pointers from dereferencing the iterator?
Yes, but I did not write the code.
Jay Beckert wrote:
Or you could try the way you have it now, declare a CString str just to hold the string from the vector on each loop passing the pointer till the end.
This is a possiblity that had not occured to me, although it adds a temporary. Thanks.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
I assume your vector is declared like this:
typedef std::vector(CString) StringVector;
If this is the case then you will need to take the address of your CString object in order to turn it into a pointer after you dereference the iterator.
for(;it != end; ++it)
{
function(&(*it));
}
By dereferencing the iterator, you are invoking the operator*(), which will return the CString object. Then to get the pointer take the address of the dereferenced iterator (*it) .
|
|
|
|
|
That was my first thought, but I'm trying to convince these people that STL is *nice*, and that is just *ugly*. There's no other way ?
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
I think that stl nice, you should just convey to the people that the iterator is an object, and in order to get access to the data that it represents, you will need to derefence it.
In the case of the vector<cstring>, if you want a pointer to a CString, you will need to take the address of the object once you have the CString.
If you wanted to do the same thing from a map iterator you would have to do this:
&(it->second)
It looks funny, but it is straight forward, but if you convey what an iterator is for and how it works, I think that people will see that it is nice rather than ugly.
|
|
|
|
|
I got a question for you guys since we're on STL. Let's say with a Map, we have .first , .second. What about third, fourth? Is it possible for a declare a Map as so;
typedef std::map< int, CString, CString, CString > MyMap;
MyMap m_map;
MyMap::iterator it;
it = m_usermap.find(int);
CString str = (*it).third;
Is this possible or would I have to write my own template?
|
|
|
|
|
No, it is not possible. You can have pretty much the same effect, however, by suitably defining the second parameter of your map s, like this:
struct string_triplet
{
std::string first;
std::string second;
std::string third;
};
typedef std::map<int, string_triplet> MyMap;
MyMap m_map;
it = m_usermap.find(i);
CString str = it->second.first;
CString str2 = it->second.second;
CString str3 = it->second.third;
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|