|
Have you ever read what I wrote? My problem is NOT that I'm running out of memory. I had enough of it before I created CFileDialog. I wanted open a file of size 880 MB, having 1.2 GB of free memory memory. But I had not a continuous block of memory after CFileDialog was destructed. One very simple but not elegant way to resolve this situation was to allocate 1.2 GB using VirtualAlloc, then create CFileDialog. It downloads its modules in memory anyway, but large block will remain intact. Memory would not be as fragmented as it was if I previously created CFileDialog. Another way, to which I came up was to create a separate process, create CFileDialog within it and return what I needed (path to file) to the parent process using one of appropriate methods (I used memory mapped file). It is a programming- there are usually many ways to do same thing. I thought about which method is the best. May be, there is a way to get CFileDialog to work more correctly than it really does. I did not dig in its source code. I do have too much problems with algorithms to waste time for such thing. When you are short of resources (few memory, weak processor and so on) it definitely makes you more disciplined. And I have no intention to buy another comp and 64 bit OS - let's my boss do it.
|
|
|
|
|
Sorry, apparently I've skipped part of your message in reading. So what you're seeing is a fragmentation of the virtual address space of your process, and that prevents the allocation of a block that doesn't fit into that space.
My next suggestion then would be to allocate a big block of memory before calling CFileDialog, like you did. You don't even need VirtualAlloc for that, you could just call new, and then create your buffer using in-place construction.
This of course requires that you know in advance the size of your file. But then, if the size would vary, there would be no point in even trying to load it into memory as a whole: if you don't know the size, you have to assume that you will eventually encounter files that don't fit into memory, no matter what!
That said, even if the file is always the same size, where is it that this aplication will run? Is it on your PC? If not, a client running the program may have less memory available than you do!
One last idea is to split the file buffer into multiple parts, allowing you to use up most of the available memory in spite of fragmentation. That way you could keep all of it in memory, just not within one contiguous block.
You could even write a wrapper class that does behave like a contiguous block of memory, but internally translates an address into a location within one of those buffers.
P.S.: here's some code to illustrate my suggestion:
template <unsigned int total_size, unsigned int chunk_size>
class DistributedBuffer {
unsigned char* blocks[1+(total_size-1)/chunk_size];
public:
DistributedBuffer() {
for (unsigned int i = 0; i < 1+(total_size-1)/chunk_size; ++i)
blocks[i] = new unsigned char[chunk_size];
}
unsigned char operator[](unsigned int offset) const {
return blocks[offset/chunk_size][offset%chunk_size];
}
unsigned char& operator[](unsigned int offset) {
return blocks[offset/chunk_size][offset%chunk_size];
}
};
int foo() {
DistributedBuffer<1024*1024*1024, 1024*1024> myFileBuffer;
myFileBuffer[12345678] = 17; unsigned char c = myFileBuffer[12345678]; return (int)c; }
modified 27-Feb-13 9:16am.
|
|
|
|
|
Thanks for tips. I think, that such class will slow my prog. As I wrote, I tried to allocate large memory block and only after it create CFileDialog. But even if I can preserve large memory block for my own use, I'll loose some volume of memory anyway- all sh*t that CFileDialog loads in my address space will stay there even after CFileDialog will have been destructed. I prefer to keep my address space clean. One way is for example to change base addresses for my libraries like FreeImage.dll, jpeglib.dll and so on- there is such useful utility named Rebase.exe. On the other hand, I'm really short of memory and this is why I prefer do not load all unnecessary libraries into address space. What I did- another separated process- gave me what I wanted. I cannot change base addresses of system libraries- it may help only if my prog runs at my own comp. There are many useful things, which can be implemented, but now the main problem for me is effectiveness of algorithms which I use.
|
|
|
|
|
Hi all. Nice to meet you. Could you tell me how can I fix the memory leak of this code? I don't have a clue. Thanks.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define MAX 100
#define BUFSZ 10
int i;
int buffindex = 0;
char* buffer;
void* producer(void* p);
void* consumer(void* p);
pthread_cond_t cond_prod = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_con = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int main(void)
{
pthread_t prod, con;
if((buffer = malloc(sizeof(char) * BUFSZ)) == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond_prod, NULL);
pthread_cond_init(&cond_con, NULL);
pthread_create(&prod, NULL , producer, NULL);
pthread_create(&con, NULL , consumer, NULL);
pthread_join(prod, NULL);
pthread_join(con, NULL);
pthread_cond_destroy(&cond_prod);
pthread_cond_destroy(&cond_con);
pthread_mutex_destroy(&mutex);
free(buffer);
return EXIT_SUCCESS;
}
void* producer(void* p)
{
for(i = 0; i < MAX; i++)
{
pthread_mutex_lock(&mutex);
if(buffindex == BUFSZ)
{
pthread_cond_wait(&cond_prod, &mutex);
}
buffer[buffindex++] = '@';
printf("Produce: %d\n", buffindex);
pthread_cond_signal(&cond_con);
pthread_mutex_unlock(&mutex);
}
pthread_exit(EXIT_SUCCESS);
return NULL;
}
void* consumer(void* p)
{
for(i = 0; i < MAX; i++)
{
pthread_mutex_lock(&mutex);
if(buffindex == -1)
{
pthread_cond_wait(&cond_con, &mutex);
}
printf("Consume: %d\n", buffindex--);
buffer[buffindex] = '\0';
pthread_cond_signal(&cond_prod);
pthread_mutex_unlock(&mutex);
}
pthread_exit(EXIT_SUCCESS);
return NULL;
}
modified 27-Feb-13 15:48pm.
|
|
|
|
|
This is a good example of how NOT to ask a question on Code Project.
You're just dumping a bunch of code and asking others to do your work.
What have you tried? Have you run this code in the debugger? Exactly which allocation is leaking?
No wonder you don't have a clue!
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Thank you for the greetings sir. First of all, I'd like to say that I'm a self taught person so... this thing of "do you think we are really going to do your homework for you?!" doesn't exist for me (did you know there are freaking bad colleges in the world?). Ah... I study in a college but the place where I study simply sucks (all my teachers try to hide the C implementation of the theory from us as much as they can and I mean ... always!). So, I decided to learn everything (as much as possible) from Computer Science by myself. So, please, take easy. I don't have a clue because I don't have anyone to teach me anything .
Back to the code ...
sorry if I didn't post the output:
Produce: 1
Produce: 2
Consume: 2
Consume: 1
Consume: 0
==2737== Thread 3:
==2737== Invalid write of size 1
==2737== at 0x400D6C: consumer (prodcon.c:72)
==2737== by 0x4E38E0D: start_thread (in /lib64/libpthread-2.15.so)
==2737== Address 0x53f203f is 1 bytes before a block of size 10 alloc
==2737== at 0x4C2ABED: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==2737== by 0x400B6D: main (prodcon.c:24)
==2737== LEAK SUMMARY:
==2737== definitely lost: 0 bytes in 0 blocks
==2737== indirectly lost: 0 bytes in 0 blocks
==2737== possibly lost: 0 bytes in 0 blocks
==2737== still reachable: 1,552 bytes in 4 blocks
==2737== suppressed: 0 bytes in 0 blocks
I appreciate the help.
|
|
|
|
|
I apologize for not understanding your situation better, but you didn't make it clear in your first post.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Quote: I apologize for not understanding your situation better
ok, no problem
Quote: but you didn't make it clear in your first post.
sorry for that too.
|
|
|
|
|
noislude wrote: ==2737== at 0x400D6C: consumer (prodcon.c:72)
...
==2737== by 0x400B6D: main (prodcon.c:24) Are these line numbers?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
yes. David you don't need to bother with this program. few hours ago, I took a detour from Modern Operating Systems to Programming with POSIX Threads to get a better understanding about threads. I apologize for the trouble.
|
|
|
|
|
The error output points at the function consumer, and the program output indicates the state before hitting the error: You're writing to an array index of -1 in this line:
buffer[buffindex] = '\0';
, after decreasing buffindex from 0 to -1 in this line:
printf("Consume: %d\n", buffindex--);
Suggested fix: change
if(buffindex == -1)
to
if(buffindex == 0)
, or better yet:
if(buffindex <= 0)
(in case you accidentally decrease buffindex multiple times; your current code doesn't seem to be able to achieve that, but code changes...)
The leak information may go away after fixing the error, it may just be a consequence of the abnormal error condition. if not, please come back with your new results.
|
|
|
|
|
I fixed the problem with the buffer index. Now I can notice three behaviors:
the first one, always producing one stuff and consuming it (in this case, I get a memory leak)
Produce: 1
Consume: 1
Produce: 1
Consume: 1
Produce: 1
Consume: 1
Produce: 1
Consume: 1
Produce: 1
Consume: 1
Produce: 1
Consume: 1
Produce: 1
Consume: 1
Produce: 1
Consume: 1
possibly lost: 272 bytes in 1 blocks
for the second behavior, I produced and consumed ten stuffs (and I got a bigger memory leak)
Produce: 1
Produce: 2
Produce: 3
Produce: 4
Produce: 5
Produce: 6
Produce: 7
Produce: 8
Produce: 9
Produce: 10
Consume: 10
Consume: 9
Consume: 8
Consume: 7
Consume: 6
Consume: 5
Consume: 4
Consume: 3
Consume: 2
Consume: 1
Produce: 1
still reachable: 1,552 bytes in 4 blocks
for the last behavior, everything went fine (without memory leaks)
Produce: 1
Produce: 2
Produce: 3
Produce: 4
Produce: 5
Produce: 6
Produce: 7
Produce: 8
Produce: 9
Produce: 10
Consume: 10
Consume: 9
Consume: 8
Consume: 7
Consume: 6
Consume: 5
Consume: 4
Consume: 3
Consume: 2
Consume: 1
Produce: 1
All heap blocks were freed -- no leaks are possible
|
|
|
|
|
I don't really see how your code can leak more than one block of memory when the entire program only allocates one!? Those leaks must be elsewhere - if those leak messages are indeed correct.
I suspect that the pthread library internally uses some kind of memory pool that doesn't get freed before the end of the program. I've seen the same thing in a CAD library that produces tens of thousands of "leak" messages because of that. It's very annoying becasue that way it's extremely difficult to pinpoint actual leaks, or find out if there even is one.
|
|
|
|
|
I see. Are those internal leaks a bad thing for a bigger program?
|
|
|
|
|
Well, if my assumption is correct, technically these aren't leaks - they just appear as such because memory pools are designed that way. If used correctly, these 'leaks' will not be a problem, except when it comes to the problem of locating real leaks.
Memory pools are used as a faster way to allocate and free lots of small blocks of memory. Basically they take up the role of a memory manager for specific types (or sizes) of objects. They may be capable of freeing unused blocks at runtime (reducing the number of "leak" messages), but doing so complicates the management effort considerably. As a consequence, most implementations never free blocks at runtime, they only grow when running out of free memory within already allocated blocks. That means the total cost of memory is the maximum load at runtime.
|
|
|
|
|
Just in case someone wonders, it was written in the book Programming with POSIX threads (the book I mentioned earlier), that we don't need to destroy (with pthread_mutex_destroy()) a mutex initialized statically i.e. with PTHREAD_MUTEX_INITIALIZER. Thank you people for all the attention given to this topic
|
|
|
|
|
I did follow this discussion which started badly – no real info was provided on the initial post, almost got into personal fist fight - “nobody spoon-fed me knowledge about programming” and ended up with no real solution to learn from.
I often wonder why people waste their time posting stuff like this.
… off my soapbox now...
|
|
|
|
|
I plan to develop a new application with Visual C++ but I am wondering which library to use for the GUI design. I.e. MFC, QT.. and so forth.
MFC is a native MS library and sounds nice but rumors say that it has no future.
What are your thoughts?
Would you start a new application with MFC?
Thanks for your answers.
|
|
|
|
|
I use VC 6.0 MFC, but I am a retired (cheap) hobbyist. I like the doc/ view “feature”.
It was suppose to simplify the windows messaging, but it made it more complicated.
May "professionals" will say that MFC lets you build quick base UI for your application, but IMHO it is a shaky foundation to build onto, adding anything requiring more that friendly, quick user interface application is a challenge using MFC.
That is why, again in my opinion, you see mostly dialog based sample codes here.
The key is in detailed planning – what do you want your app to accomplish.
And as far as future of MFC – I see a continuing trend to abuse “object oriented” hiding of the actual process and “foundation” is just another name for “wrapper”.
In short – do not use MFC if you want true control of your code.
Cheers Vaclav
|
|
|
|
|
Vaclav_Sal wrote: “foundation” is just another name for “wrapper”
MWC = "Microsoft Wrapper Classes?"
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
No future.
GUI developmeng is no future, too.
Algorithm is king.
|
|
|
|
|
yu-jian wrote: GUI developmeng is no future
What? Complete and utter rubbish. The UI is now more important than it has ever been.
|
|
|
|
|
MFC is burdened with several decades of legacy, and full of bad designs and ugly interfaces. You won't notice a lot of it when designing a small GUI project, but for serious, long-lived work, it is most certainly not a good choice.
However, your choice depends a lot on the application you plan to build:
- If you want to build one for the MS App Store, you probably have to build it on the basis of WinRT, not MFC.
- If you want one that runs on Win7, WPF is a better, more modern library than MFC.
- If in the long (or short) run you don't want to restrict your application to just Windows, you need a platform-independend framework like QT.
|
|
|
|
|
I agree with you.
It is a painful thing to use the MFC develop a GUI product. I need to use the GDI+ to make many self-define controls. The C# is more convient than MFC.
|
|
|
|
|
I would develop the user interface in C# and try to put the logic in VC++ if at all it is a mandate.
You talk about Being HUMAN. I have it in my name
AnsHUMAN
|
|
|
|