|
I'm not used to create my own libraries in C++ (Did it dozens of times in java), but now I want to create one implementing easy to use logging functions.
MyLog.lib is a win32 static library. It works fine when linked from an ordinary win32 console application.
But, when trying to implement it in an MFC application, I get numerous linking errors.
Did I forget something? Is it possible to link to a win32 library from an MFC app?
tnx
using: [VISUAL STUDIO 6.0 sp5] [WIN98/2]
|
|
|
|
|
Zizilamoroso wrote:
I get numerous linking errors.
Which? What is the linker complaining about?
Who is 'General Failure'? And why is he reading my harddisk?!?
|
|
|
|
|
Linking...
LIBCD.lib(crt0dat.obj) : error LNK2005: _exit already defined in msvcrtd.lib(MSVCRTD.dll)
LIBCD.lib(crt0dat.obj) : error LNK2005: __exit already defined in msvcrtd.lib(MSVCRTD.dll)
LIBCD.lib(crt0init.obj) : error LNK2005: ___xc_z already defined in msvcrtd.lib(cinitexe.obj)
LIBCD.lib(crt0init.obj) : error LNK2005: ___xc_a already defined in msvcrtd.lib(cinitexe.obj)
LIBCD.lib(crt0init.obj) : error LNK2005: ___xi_z already defined in msvcrtd.lib(cinitexe.obj)
LIBCD.lib(crt0init.obj) : error LNK2005: ___xi_a already defined in msvcrtd.lib(cinitexe.obj)
LIBCD.lib(winxfltr.obj) : error LNK2005: __XcptFilter already defined in msvcrtd.lib(MSVCRTD.dll)
msvcrtd.lib(MSVCRTD.dll) : error LNK2005: __setmbcp already defined in LIBCD.lib(mbctype.obj)
LINK : warning LNK4098: defaultlib "msvcrtd.lib" conflicts with use of other libs; use /NODEFAULTLIB:library
LINK : warning LNK4098: defaultlib "LIBCD" conflicts with use of other libs; use /NODEFAULTLIB:library
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/Test.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
using: [VISUAL STUDIO 6.0 sp5] [WIN98/2]
|
|
|
|
|
You seem mix up the runtime libraries. Please check your project settings: You need to have *ALL* projects set to using either "multithreaded" *OR* "multithreaded dll".
Maybe you need to make both versions of your library for use in different projects.
Who is 'General Failure'? And why is he reading my harddisk?!?
|
|
|
|
|
They're both "debug multithreadeded", but the mfc app was "debug multithreaded dll". The " dll" piece of the string fell out of the combobox' window bounds )) So, that's why I didn't saw this one.
I demand larger comboboxes in VC!!! ) lol
tnx jhwurmbach
using: [VISUAL STUDIO 6.0 sp5] [WIN98/2]
|
|
|
|
|
Now it works?
Great!
Who is 'General Failure'? And why is he reading my harddisk?!?
|
|
|
|
|
hello friends
Can any one tell me
How to create Common Browse Dialog box for folder selection which contains TreeCtrl with check boxs in it.
Thanx
TAKE CARE
|
|
|
|
|
Simple! Just look at the articles already on the site here.
For example, take the article "Browse For Folder" dialog alike with source[^] and adapt
it by adding the checkbox style to the tree, and adding accessor methods for the check data.
Should only take you 30 seconds...
Other articles may give you inspiration.
Iain.
|
|
|
|
|
i have 2 projects in the same workspace, namely SDI database and another SDI based dialog, i wish to link up the database to my dialog, how to do this?
|
|
|
|
|
Hi all, back with a slightly different issue. OK, here's what I'm trying to do:
I'm writing a template container class for a dynamic array (similar to the vector class). The class will be used as a basis for my own custom string allocation and more complex class structures. With this in mind, operator new in its standard form has not been implemented because it cannot be used to expand memory, I would, in effect, have to new another block of memory and copy the contents over before deleting the old block, this is slow and prone to mistakes. Therefore malloc has been implemented, with realloc, to handle the actual memory allocations. However, the problem with malloc is that it never calls the constructor for the object you want to store, it just allocates raw bytes. BUT, does this mean I could use placement new to initialise a block of memory with type T as follows:
<br />
T* p = malloc(sizeof(T));<br />
if(p)<br />
{<br />
new (p) T;<br />
}<br />
I would like to be able to call the constructor for each object in the malloc'ated area but similarly I can't use new cos I want it to be fast AND dynamic. Any good links, ideas, suggestions on how I'm going about this would be very much appreciated. This class will be a foundation for many things and I need it to be neat, at the moment it works, but its buggy cos things aren't getting constructed properly. Thanks guys.
|
|
|
|
|
Well, first off, I've gotta say thanks - I learnt a new thing today - I was never aware of the placement syntax :/
Mixing C-style and C++ style memory allocations is not a good idea since they use separate memory managers. You could replace your malloc(sizeof(T)) with new char[sizeof(T)] . Realloc would still present you with the copying problem - infact, if realloc can't extend the memory area it will create a completely new area and perform a copy operation.
It does look like the placement syntax enables you to give an explicit address for the object you wish to dynamically create - it also looks like that will remove the overhead of the memory manager actually finding a suitable sized piece of free memory. So, I am thinking you are on the right track here.
[EDIT]
One thing I forgot to mention was that when you do use placement new, Stroustrup states that you need to explicitly call destructors for objects when you want to delete them - this makes sense since the memory manager is being bypassed.
[/EDIT]
However, you may want to consider creating space for several objects each time you need to reserve space i.e. new char[N*sizeof(T)] . Now create you own memory management scheme that uses that pool of memory with placement new. When that area is exhausted, create another pool. This has the effect of reducing the number of times the standard new operator needs to be called - thus reducing overhead. Ok, you have to manage each pool but working with fixed sized objects within each pool should be fairly efficient to to. There is a book called "Efficient C++" which looks at these issues in some detail.
Hope this helps
Phil
|
|
|
|
|
Yes, I had thought about allocating a couple of extra places and then when they are filled grabbing a new block and copying the contents in, which is essentially what realloc utilises. This is definitely one option, and is probably the way that the vector class works (in fact you can define its growth factor). However, I was hoping to come up with a nice tight memory usage, that makes things easy to use. The idea of placement new seems like what I want, 'use this memory address to initialise with this item'. I don't think it actually allocates any memory see, just initialises it with the item you supply. As you stated, I'd then have to whip through the array and call the destructor for each object manually, but this can be arranged . If realloc needed a new memory block, the contents of my already initialise data would be copied in - no destructor is called, which is great because it were, when the array class destructor was called it would delete the same objects again . I think I may be on the right lines, just waiting for someone to prove otherwise . Thanks for your comments though Phil, they were very encouraging, which is something I need at the minute cos I've been on this a little while .
Many Thanks,
Alan.
|
|
|
|
|
Alan,
You shouldn't need to perform any copying. The idea of creating a memory block/pool that is several times larger than the object(s) you want to place within it is to reduce the number of times malloc or new are called (not placement new). When you have filled that block, allocate another and start using that one (you will now have two blocks containing object - there should be no need to copy the contents of your original block to the second one). Keep doing this for as long as you need space to store your objects. A scheme such as a two-way linked list that forms a header at the top of each block will enable you to keep track of each one allocated - and provide a mechansim to remove blocks once all the objects it contains are deleted. This should still be fairly efficient. Actually, I'm pretty sure this is how vector is implemented and I think the growth factor effectively determines the block/pool size used.
Cheers,
Phil
|
|
|
|
|
Yeah I see what your saying, its just because I'm creating a template container class for arrays of objects (I've already done one for linked lists), so I didn't really want to mess with having multiple new'd pointers (I wanted to be able to use pointer addition ). Your right about the vector implementation, but I'm looking for a way of manipulating one contigous block of memory. I had thought of reserving larger chunks, and your solution of reserving another chunk is smart, but I'd like to see how much I can squeeze out one contigous memory block before I opt for plan B.
Alan.
|
|
|
|
|
Also, take a look here[^] for some more info. The bit about alignment is worth noting!
Phil
|
|
|
|
|
Thanks again Phil, I'm pretty sure alignment won't be a problem because malloc handles the correct alignment for buffers depending on their size (it doesn't matter exactly what object they are, only the size of the object will determine whether malloc has to pad the memory with x bytes to align it ). Cheers for that article mind, very helpful explanation of placement new, which is new to me myself. Thanks again for your help Phil, much appreciated,
Alan.
|
|
|
|
|
I'm not sure realloc will be more efficient than doing another new and copying. That's what realloc does beneath the surface, anyway. You only literally 'expand' an allocated space with realloc on those rare occasions where you have not done any other memory allocations since you malloc'd the memory you are expanding.
I'd look into how efficient you can get the STL using custom allocator classes before you go as far as reimplementing a string class.
|
|
|
|
|
I think realloc will be faster when it comes to large objects because it will merely allocate a larger block of memory and copy the contents over - no destructors or constructors are called, therefore everything is A1. Also, new does have extra overhead because of the try,throw,catch implementation. However, using new/delete I'd have to reserve another memory block, but how pray do I move the objects into the new array? If I merely copy the bytes across, when I free up the previous allocation the objects destructor is called and so, those objects in the new array are total garbage (and they will get deleted again the next time a reallocation is made. Nasty. Any ideas on how to get around that would be very useful, and I would definitely use that method instead .
Cheers,
Alan.
|
|
|
|
|
Hi,
I am an amateurish user of VC++. I am developing a program which handles lots of picture files and works with them. The entire operation is carried on a FormView. The picture files are loaded one at a time. I have inserted few functions in the onmousemove() because the requirement was such. Now as the program runs, it goes on gathering memory requirement in a cumulative way (seen through task manager) untill the OS stops the program forcefully. I tried to allocate memories dynamically and freed them whereever the purpose is finished. But mothing worked.
Only one thing drastically brings down the memory, is when the Frame is minimized and again maximized.
What could be the reason for what is happening. Could you give a clue to how to reduce the memory requirement, or where exactly I can free some. The minimization process frees the memories automatically. Does it give some clue?
Thanks in advance
|
|
|
|
|
You have a nasty memory leak! Somewhere in your program, memory is being allocated, but is never being freed, at least in time before your out of memory. Its likely to be something to do with your loading of the pictures, or perhaps drawing of the pictures? Are you using GDI to draw them? If you are make sure you are keeping track of your handles correctly. What are you doing in your minimize/maximize functions that would reduce memory? On maximize, the app has to redraw the the view, which is why I think its something to do with your pictures/drawing of the pictures. Post some code up!
|
|
|
|
|
I'm loading a BMP file with the Attach function of CBitmap and displaying on the formview through the StretchBlt() of CDC.
|
|
|
|
|
OK, Attach takes one param, a handle to an object, how are you getting this handle? Where are you getting this handle? Where are you attaching this handle? When do you destroy this handle? Can you post up your draw code so we can at least see the bigger picture of your drawing process?
|
|
|
|
|
I'm posting it, sorry it must have been a very very clumsy one -
CString filename;
char szFilters[]="Picture Files(*.bmp)|(*.gif)|All Files(*.*)|*.*||";
CFileDialog dlg(TRUE,"bmp","*.bmp",OFN_FILEMUSTEXIST|
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
szFilters,this);
if(dlg.DoModal()==IDOK)
{
filename=dlg.GetPathName();
}
else return;
OnNewFileLoaded();
bBitmap.Detach();
/*m_Bit.SetBitmap(LoadImage(filename.GetBuffer(20)));*/
bBitmap.Attach((HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE));
// m_Bit.SetBitmap((HBITMAP)bBitmap);
// m_TextDisplay.SetWindowText("Please Click on the Origin of the graph's axes"
// "and Press the DONE button");
CDC* pDC = GetDC();
CBrush brush(pDC->GetPixel(1,1)),*oldbrush;
oldbrush = pDC->SelectObject(&brush);
pDC->FloodFill(7,7,pDC->GetPixel(1,1));
pDC->SelectObject(oldbrush);
BITMAP BM;
if(bBitmap.GetObjectType()==0) {
AfxMessageBox("Invalid File Format.\nLoads only Bitmaps.");
return;
}
bBitmap.GetObject(sizeof(BM),&BM);
CRect rectClient;
GetClientRect(&rectClient);
if(rectClient.Height()<bm.bmheight||rectclient.width()<bm.bmwidth)
{
="" cmainframe*="" pmain="(CMainFrame*)" getparentframe();
="" pmain-="">ActivateFrame(SW_SHOWMAXIMIZED);
AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
}
if(WIDTH>BM.bmWidth&&HEIGHT>BM.bmHeight){
destWidth = BM.bmWidth;
destHeight = BM.bmHeight;
}
else if(WIDTH>BM.bmWidth&&HEIGHT<bm.bmheight){
destwidth="(int)(destHeight*((double)BM.bmWidth/(double)BM.bmHeight));
" }
="" else="" if(width<bm.bmwidth&&height="">BM.bmHeight){
destHeight = (int)(destWidth*((double)BM.bmHeight/(double)BM.bmWidth));
}
else
{
if(BM.bmWidth>BM.bmHeight){
destWidth = WIDTH;
destHeight = int((double(BM.bmHeight)/double(BM.bmWidth))*double(destWidth));
}
else{
destHeight = HEIGHT;
destWidth = int((double(BM.bmWidth)/double(BM.bmHeight))*double(destHeight));
}
}
CPoint ratio;
ratio.x= destWidth;
ratio.y= destHeight;
ratioHeight = (double)BM.bmHeight/(double)ratio.y;
ratioWidth = (double)BM.bmWidth/(double)ratio.x;
CMainFrame* pMain= (CMainFrame*) GetParentFrame();
CToolBarCtrl* pCtrl = (CToolBarCtrl*)pMain->GetToolBar();
if(pCtrl->IsButtonChecked(ID_TOOLZOOM)){
OnToolzoom();
}
if(m_ShowZOOM.IsWindowVisible()) m_ShowZOOM.ShowWindow(FALSE);
RedrawWindow(NULL,NULL);
if(!rectBitmap.IsRectEmpty())this->ValidateRect(&rectBitmap);
if(HBITMAP(bBitmap)!=NULL){
BITMAP BM;
CDC MemDC;
MemDC.CreateCompatibleDC(NULL);
MemDC.SelectObject(bBitmap);
if(bBitmap.GetObjectType()==0){
AfxMessageBox("Invalid File Format.\nLoads only Bitmaps.");
return;
}
bBitmap.GetObject(sizeof(BM),&BM);
GetDC()->StretchBlt(7,7,destWidth,destHeight,&MemDC,0,0,BM.bmWidth,BM.bmHeight,SRCCOPY);
rectBitmap.top = 7;rectBitmap.left = 7;rectBitmap.bottom = destHeight+7;
rectBitmap.right = destWidth+7;
GetDC()->DPtoLP(&rectBitmap);
|
|
|
|
|
OK, we're starting to get somewhere now. If this is you OnPaint() or whatever draw function, there is no need to be keep loading the picture in. What seems to be happening is LoadImage is loading a handle to a resource each time this function is called, but it is never freed. With bitmaps this is vital because you will soon run out of memory. Detaching the handle is not enough to free the memory allocated to the handle. I would store the result of your LoadImage call as a member HANDLE (alongside bBitmap) in the class that calls this draw function. I would also separate the file loading code so when you click, perhaps a button, the filedialog is called, if the HANDLE is NULL it then simply allocates a new one using LoadImage, otherwise use Detach on bBitmap followed by DeleteObject on the existing HANDLE, before LoadImage on the new pic. This frees your draw code to concentrate on drawing, no monster leaks would occur because everything you use to draw is in memory and isn't changing (only time it changes is when you click THE button and choose a file). This is definitely where A monster leak would be occurring, perhaps it is THE monster leak .
|
|
|
|
|
You can use the features in Visual Studio to detect where memory is eaten. Run the program in debug mode ( press F5 ), and take your program through all the scenarios where there are possiblities of leak. Stop the application, and see the debug tab in output window. There you can see all the memory locations which has not been freed. Double clicking on it will take you to the position in code where that memory is allocated.
Hope this can be of your help.
"A robust program is resistant to errors -- it either works correctly, or it does not work at all; whereas a fault tolerant program must actually recover from errors."
|
|
|
|
|