 |
|
 |
Hello,
I compiled your code with Visual Studio 2005 with the C++ Code Analysis enabled an get the following warnings:
.\DLLFileEntry.cpp(170) : warning C4189: 'error' : local variable is initialized but not referenced
.\pathentry.cpp(220) : warning C4100: 'theStream' : unreferenced formal parameter
main.cpp(66) : warning C6246: Local declaration of 'theFE' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '43' of 'main.cpp': Lines: 43
main.cpp(85) : warning C6246: Local declaration of 'theFE' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '43' of 'main.cpp': Lines: 43
filefinder.cpp(125) : warning C6011: Dereferencing NULL pointer 'TeFS': Lines: 55, 83, 85, 86, 96, 101, 102, 107, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125
filefinder.cpp(229) : warning C6011: Dereferencing NULL pointer 'TE': Lines: 225, 226, 227, 228, 229
filefinder.cpp(231) : warning C6011: Dereferencing NULL pointer 'thePaths': Lines: 225, 226, 227, 228, 229, 230, 231
filefinder.cpp(315) : warning C6053: Call to 'strncpy' might not zero-terminate string 'chPathName': Lines: 225, 226, 227, 228, 229, 230, 231, 232, 237, 238, 276, 277, 278, 279, 282, 283, 311, 312, 314, 315
filefinder.cpp(322) : warning C6011: Dereferencing NULL pointer 'TeFS': Lines: 225, 226, 227, 228, 229, 230, 231, 232, 237, 238, 276, 277, 278, 279, 282, 283, 311, 312, 314, 315, 316, 317, 318, 319, 320, 321, 322
filefinder.cpp(258) : warning C6011: Dereferencing NULL pointer 'theDir': Lines: 225, 226, 227, 228, 229, 230, 231, 232, 237, 238, 240, 241, 247, 248, 249, 256, 257, 258
collections.h(193) : warning C6244: Local declaration of 'temp' hides previous declaration at line '32' of 'filefinder.cpp'
collections.h(1058) : warning C6244: Local declaration of 'temp' hides previous declaration at line '32' of 'filefinder.cpp'
collections.h(1069) : warning C6011: Dereferencing NULL pointer 'temp': Lines: 1047, 1049, 1055, 1058, 1060, 1066, 1067, 1069
collections.h(1080) : warning C6011: Dereferencing NULL pointer 'iterator': Lines: 1047, 1049, 1055, 1058, 1060, 1066, 1067, 1069, 1077, 1079, 1080
collections.h(1270) : warning C6244: Local declaration of 'temp' hides previous declaration at line '32' of 'filefinder.cpp'
fileentry.cpp(102) : warning C6283: 'temp' is allocated with array new [], but deleted with scalar delete: Lines: 98, 102
dllrtloader.cpp(69) : warning C6011: Dereferencing NULL pointer 'theDLLs': Lines: 47, 48, 53, 59, 61, 66, 67, 69
dllfileentry.cpp(176) : warning C6011: Dereferencing NULL pointer 'TeFunc': Lines: 149, 150, 151, 152, 157, 158, 159, 161, 162, 167, 174, 175, 176
directoryentry.cpp(106) : warning C6283: 'temp' is allocated with array new [], but deleted with scalar delete: Lines: 102, 106
child\dllproxychild.cpp(58) : warning C6011: Dereferencing NULL pointer 'myDLLFE': Lines: 53, 54, 55, 57, 58
.\Child.def(4) : warning LNK4017: DESCRIPTION statement not supported for the target platform; ignored
Could you please correct this.
Thanks,
Andreas.
|
|
|
|
 |
|
 |
Hello,
the include iostream.h must be changed to iostream in both stdafx.h, otherwise Visual Studio 2005 don't compile.
The include fstream.h in file collections.h must be replaced by fstream, and the missing
std:: must be added to the function parameter ostream.
In main.cpp the missing std:: must be added to cerr and the variable definition unsigned int is missing for variable count in the last for loop.
I get the following errors/warning compiling file DLLFileEntry.cpp:
1>.\DLLFileEntry.cpp(170) : warning C4189: 'error' : local variable is initialized but not referenced
1>.\DLLFileEntry.cpp(209) : error C2676: binary '<<' : 'ostream' does not define this operator or a conversion to a type acceptable to the predefined operator
1>.\DLLFileEntry.cpp(213) : error C2676: binary '<<' : 'ostream' does not define this operator or a conversion to a type acceptable to the predefined operator
1>.\DLLFileEntry.cpp(215) : error C2676: binary '<<' : 'ostream' does not define this operator or a conversion to a type acceptable to the predefined operator
and compiling pathentry.cpp:
1>.\pathentry.cpp(222) : error C2676: binary '<<' : 'ostream' does not define this operator or a conversion to a type acceptable to the predefined operator
1>.\pathentry.cpp(223) : error C2676: binary '<<' : 'ostream' does not define this operator or a conversion to a type acceptable to the predefined operator
Andreas.
|
|
|
|
 |
|
 |
Dear Gert,
I have tried re-building the project in VS2005 and get crashes on destruction of various objects in Debug mode. For example, the application fails at:
template INLINE DynamicArray::~DynamicArray()
{
if (myArray != NULL)
{
// remove all elements first, this means they will not be deleted.
RemoveAll();
delete myArray; // CRASH HERE
}
}
myArray is not NULL and I can't see why it would fail. Any ideas?
|
|
|
|
 |
|
 |
Hello
Thanks for a great article.
I just want to make sure about something. Does your framework support MFC plugins ? I want to make a plugin with a configuration dialog based within the same dll. I noticed that in your DLLProxy you make use of LoadLibrary and not AfxLoadLibrary, thus makeing the framework not safe for MFC dll's.
Thanks
|
|
|
|
 |
|
 |
Hi,
This is probably the wrong place to ask, but...
Is there any way of extracting functions from a DLL removing the dependancy on the DLL and allowing code that uses the DLL functions to function as a stand-alone ?
Failing that, is there any way to include a DLL in an executable/DLL, again so that it can run stand-alone ?
|
|
|
|
 |
|
 |
Hi Dears
I've created a VC++/ATL Com Add-in for MS Outlook, to delete mail attachments.
Now please guide me how to make Installation Program to load ATL Com Add-in(.dll) with MS Outlook ? so that the user with no Visual Studio can also use the add-in.
Please guide me ..............
I'm very grateful to you.
Kind Regards
Atif (abqau@hotmail.com - abqau@yahoo.com)
Watch Your Thoughts for they will become your actions.
Watch Your Actions for they will become your habits.
Watch Your Habits for they will become your beliefs.
Watch Your Beliefs for they will determine your destiny.
|
|
|
|
 |
|
 |
Nice article. It made using plug in a lot easier.
but how do i send events from plug in dlls. My dll will implement some functions like do_something() but also need to send some notifications back to the client using the dll.
Please help
Thanks and Regards,
Amit
|
|
|
|
 |
|
 |
Hello Dears
I'm student. I've to make a plug-in for MS Outlook. This plug-in will take a particular date, and will delete all the attchments of the e-mails which are older than that specific date.
Kindly guide me for the task. Provide/guide me some sample code if possible. I'll be very grateful to you.
Waiting for your kind response.
Atif
Watch Your Thoughts for they will become your actions.
Watch Your Actions for they will become your habits.
Watch Your Habits for they will become your beliefs.
Watch Your Beliefs for they will determine your destiny.
|
|
|
|
 |
|
 |
Hello,
I get the folowing warnings when compiling with VC7 and /Wp64 Flag set:
pathentry.cpp(42) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
pathentry.cpp(75) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
pathentry.cpp(96) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
pathentry.cpp(125) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
pathentry.cpp(139) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
filefinder.cpp(67) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
filefinder.cpp(85) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
filefinder.cpp(115) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
fileentry.cpp
fileentry.cpp(67) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
fileentry.cpp(87) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
directoryentry.cpp(70) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
directoryentry.cpp(92) : warning C4267: 'initializing' : conversion from 'size_t' to 'unsigned int', possible loss of data
Could you please update your code, or do I have to change this by myself?
Thanks a lot,
Andreas.
|
|
|
|
 |
|
 |
Hy.
I tried to make a program to work under .NET (Visual C++ 7) and for some strange reason, i always get a "Heap Validate Error" when using the ::LoadLibrary and ::FreeLibrary.
For testing i took a sample program from VC 6 wich works without any problems, and compiled both the plugin and the application with .NET
I even tried to recreate the main application an plugin DLL under .NET and add the plugin code afterwards, but i got the same error.
Does anybody know what's happening ?
"If you give someone a program, you will frustrate them for a day
but if you teach them how to program, you will frustrate them for a lifetime."
Programmer's curse
|
|
|
|
 |
|
 |
Hello,
I think its a bug in the MS .NET compiler,
if you disable "Program Database for edit&continue" in the "C/C++ General Settings" Page,
"Debug Information Format" or set it to "Program Database" it should work fine.
See Q318669 in MS Knowledge Base for more information.
If you are loading a MFC Extension DLL, you should replace LoadLibrary with AfxLoadLibrary
and FreeLibrary with AfxFreeLibrary.
See MSDN.
Greetings,
Andreas.
|
|
|
|
 |
|
 |
Hi Boddaert,
I've implemented the plugin architecture in my project. My question is if there are more than 1 DLL in my application - is there any chance of address collision when OS loader loads them ??
Because books say that by default the linker will set the image base for the 1st DLL as 0x10000000 and this default address will be applied to all of DLLs. So do I need to use some sort of 'rabasing' technique when there are more than 1 DLL ?
Any comments will be highly appreciated.
Thanking You,
Kuntal Mondal
|
|
|
|
 |
|
 |
You do not need to rebase the DLL, but if you want to speed up loading you can...
--------------------------------------------------
If my messages appear curt, I apologize.
I try to be brief to save your time as well as mine.
--------------------------------------------------
|
|
|
|
 |
|
 |
It is best practice, but only a few do it.
(I would if I had to compile dlls).
Try this @ home. (B&B)
|
|
|
|
 |
|
 |
Hi,
In Line 47 and 104 of filefinder.cpp you call
delete myFileFilter,
but myFileFilter is a created by
myFileFilter = new char[length]
The call to delete must be
delete [] myFileFilter.
The same error occures in pathentry.cpp in line 65 and 91 with 'myPath'
and collections.h line 2137 and 2166 with 'myKey'
Use the same form in corresponding uses of new and delete!!!
Andreas.
|
|
|
|
 |
|
 |
Fortunately (for me) the current versions of the MS compilers are not completely ANSI compliant and for char*'s allocation/deallocation there is something like backward compatibility. (unless they skipped it in VC7?)
But of course, you are right.
new -- delete
new [] -- delete []
I did change this a while ago in my own code but for the above-mentioned reason, I did not find it necessary to patch it in the submitted code.
BR,
Gert.
--------------------------------------------------
If my messages appear curt, I apologize.
I try to be brief to save your time as well as mine.
--------------------------------------------------
|
|
|
|
 |
|
 |
What do you mean with:
Fortunately (for me) the current versions of the MS compilers are not completely ANSI compliant and for char*'s allocation/deallocation there is something like backward compatibility. (unless they skipped it in VC7?)
A call to new -- must follow a call to delete
and a call to new [] -- must follow a delete []
There is another error (memory leak) in collections.h in line 229:
The function:
template INLINE void DynamicArray::DeleteAll(void)
{
for (unsigned int teller = 0; teller < myNumberOfElements; teller++)
{
delete myArray[teller];
}
myNumberOfElements = 0;
}
deletes all objects in myArray, but what is with myArray self?
This function is called from
DLLRTLoader::~DLLRTLoader()
{
myDLLs.DeleteAll();
myFuncNames.DeleteAll();
}
i think it should delete myArray too, or am i wrong?
If not it has to be changed to
template INLINE void DynamicArray::DeleteAll(void)
{
for (unsigned int teller = 0; teller < myNumberOfElements; teller++)
{
delete myArray[teller];
}
delete [] myArray;
myNumberOfElements = 0;
}
Greetings,
Andreas.
|
|
|
|
 |
|
 |
C++ Hacker wrote:
A call to new -- must follow a call to delete
and a call to new [] -- must follow a delete []
you misinterpreted...
The general rule is: when you allocate an array with "new [x]", you have to delete it with "delete []", when you allocate a single object with "new", you have to delete it with "delete".
The MS VC compiler has a feature which allows you to delete a char array with "delete" although the "new char[x]" was used for the allocation (check for a memory leak with boundschecker, purify or any other memory validator, there isn't one). One should avoid this feature since it is not ANSI compliant code: you will have a leak when using another compiler or platform.
C++ Hacker wrote:
i think it should delete myArray too, or am i wrong?
"delete myArray" is done in the destructor of the collection object. There is no leak there either. myArray is destroyed when it is no longer needed, not before.
See what happens when you add some elements to the collection object, then delete them all with DeleteAll(), then add some elements again: as long as myArray is big enough to hold all the pointers to the elements, no deallocation and reallocation takes place.
I hope everything is clear now.
Gert.
--------------------------------------------------
If my messages appear curt, I apologize.
I try to be brief to save your time as well as mine.
--------------------------------------------------
|
|
|
|
 |
|
 |
Hi There,
I'm currently installing your plugin architecture into my program. But I've got this assertion failure in DLLFilentry::MapIn.int CDLLFileEntry::MapIn(void) {
_ASSERT( myLibHandle == NULL );
char* completepath = GetCompletePath();
_ASSERT( completepath != NULL);
_ASSERT( myRefCount == 0 );
_ASSERT( myMapped_In == false );
SetLastError(ERROR_SUCCESS);
myLibHandle = ::LoadLibrary( completepath
);
DWORD error = GetLastError();
if (myLibHandle == NULL)
{
if (error == ERROR_SUCCESS)
{
return -1;
}
return error;
}
if (error != ERROR_SUCCESS)
{
_ASSERT(NULL); SetLastError(ERROR_SUCCESS);
}
myMapped_In = true;
return ERROR_SUCCESS;
}The assertion failure occurs on the line of your code with the comment "mapped in, but error ? (happens when using purify!)". Do you have any ideas what could be causing the problem? What does "happens when using purify" actually mean? Any help you can offer is most welcome.
With time we live, with money we spend!
Joel Holdsworth
|
|
|
|
 |
|
 |
Hi,
I seem to remember I got this error when I used rational purify. Are you using any kind of memory bounds checking program?
Anyway I think you can ignore it, but check whether the GetProcAddress function calls succeed.
BR,
Gert.
--------------------------------------------------
If my messages appear curt, I apologize.
I try to be brief to save your time as well as mine.
--------------------------------------------------
|
|
|
|
 |
|
 |
Hello!
Your article has showed me some nice techniques to properly address the problem of explicitly binding C++ code at run-time. But here is one of my main concerns that nobody has been able to satisfactorily answer yet (and apart from a few test sources, I have no evidence that it may work or may not work).
Question: Will this work even if the plug-in DLL was compiled using
a) an earlier/later version of the
b) a completely different
Compiler? e.g. I make my project open source, and people start writing plugins and compiling them with g++ or Borland C++...
I seriously doubt that the VMT and other virtual method management components will work when it comes to passing on derived/encapsulated/abstract classes from one dll to another and each of them being built using an arbitrary (though, for simpicity's sake, lets say ISO-compilant) compiler.
Unfortunately, I haven't found a single resource up to date that addresses the problem, except for a talk I had with another programmer years ago, who told me that the way virtual methods are managed can even change from one service pack to the next of the same compiler suite.
--
Moritz Voß
|
|
|
|
 |
|
 |
Hi,
Moritz Voss wrote:
I seriously doubt that the VMT and other virtual method management components will work when it comes to passing on derived/encapsulated/abstract classes from one dll to another and each of them being built using an arbitrary (though, for simpicity's sake, lets say ISO-compilant) compiler.
I share your doubt. I seem to remember (without checking the ISO specs) that the implementation of the Virtual function mechanism (dynamic binding) is not defined by the standard. So of course the behavior is strictly defined and specified but every compiler creator and builder is free to choose its specific implementation. Hence it is indeed possible that plugins will misbehave if they are using virtual function calls across DLL boundaries when the DLLs and/or the main program are compiled with different compilers. However if one would wrap the virtual function calls so that the the dynamic binding is not exposed across the module boundaries, then it should work, but that seriously diminishes the flexibility. You could also use COM... So, in fact I must admit I do not have the answer to that one...
BR,
Gert.
--------------------------------------------------
If my messages appear curt, I apologize.
I try to be brief to save your time as well as mine.
--------------------------------------------------
|
|
|
|
 |
|
 |
The author answered almost every posting in the comments, which is not always the case. It's a good example for others. If one posts an article, he should also be interested in people's reaction and answer the arising questions.
|
|
|
|
 |
|
 |
Hi,
I am explicitly linking a dll to a an executable. It gives me error at RUNTIME. Err msg says- "The value of ESP was not saved properly across a function call...result of function declared with one calling convention and function pointer declared with different calling convention".
My function in the dll is -
#define DllExport __declspec( dllexport )
extern "C" DllExport int LoginInformation( char *user_name, char *password);
extern "C" int LoginInformation(char *user_name, char *password)
{
strcpy((char *)user_name,"sa");
strcpy((char *)password,"sa");
return 1;
}
and the function pointer declaration while explicit linking is -
typedef int (CALLBACK* LPFNDLLFUNC1)(char *, char *);
HINSTANCE hDLL; // Handle to DLL
LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer
char * user_name;
char * password;
int status;
user_name = (char *)malloc(10*sizeof(char));
password = (char *)malloc(10*sizeof(char));
hDLL = LoadLibrary("custpassauth.dll");
if (hDLL != NULL)
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,"LoginInformation");
status = lpfnDllFunc1(user_name,password);
}
FreeLibrary(hDLL);
return 1;
}
Any help would be welcome.
TIA
Saurabh
|
|
|
|
 |
|
 |
you answered your own question:
typedef int (CALLBACK* LPFNDLLFUNC1)(char *, char *);
CALLBACK boils down to the __stdcall calling convention.
extern "C" int LoginInformation(char *user_name, char *password);
since you did not specify the calling convention for this function, the project's default calling convention will be used which usually is the __cdecl calling convention.
So the solution to your problem is to specify the CALLBACK (== __stdcall) calling convention for the function declaration and implementation.
declaration (in .h):
extern "C" int CALLBACK LoginInformation(char *user_name, char *password);
implementation (in .cpp):
extern "C" int CALLBACK LoginInformation(char *user_name, char *password)
{
// your implementation
}
BR,
Gert.
--------------------------------------------------
If my messages appear curt, I apologize.
I try to be brief to save your time as well as mine.
--------------------------------------------------
|
|
|
|
 |
|