Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Контроль памяти и image file


Автор: CPlusPlusFAN 22.3.2008, 19:34
Нет. Я не ошибся разделом. Это действитьльно по C++.
Я запускаю jar файл с контролем памяти:

Код

    DEBUG_EVENT de;
    de.u.CreateProcessInfo.hFile=NULL;

    CreateProcess(process,command,NULL,NULL,FALSE,
                  flag,
                  NULL,directory,&StartInfo,&ProcInfo);

    if (!exception)
    //На это не обращать внимания
        WaitForSingleObject(ProcInfo.hProcess,wait);
    else
    {
        //Вот отсюда смотреть
        bool works=true,first=true,rs;
        DWORD status=DBG_CONTINUE;
        
        HANDLE hJob=CreateJobObject(0,"");
        JOBOBJECT_EXTENDED_LIMIT_INFORMATION jl={};
        jl.BasicLimitInformation.LimitFlags=JOB_OBJECT_LIMIT_PROCESS_MEMORY;
        jl.ProcessMemoryLimit=mem;
        SetInformationJobObject(hJob,JobObjectExtendedLimitInformation,&jl,sizeof(jl));
        AssignProcessToJobObject(hJob,ProcInfo.hProcess);

        while (works)
        {
            rs=WaitForDebugEvent(&de,wait)!=0;

            if (!rs)
                TerminateProcess(ProcInfo.hProcess,0);
            else
                if (de.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT)
                    works=false;
                else
                    if (de.dwDebugEventCode==EXCEPTION_DEBUG_EVENT)
                        //Ошибки

                ContinueDebugEvent(de.dwProcessId,de.dwThreadId,status);
        }

        if (de.u.CreateProcessInfo.hFile!=NULL)
             CloseHandle(de.u.CreateProcessInfo.hFile);
        CloseHandle(hJob);
    }

    TerminateProcess(ProcInfo.hProcess,0);

    CloseHandle(ProcInfo.hThread);
    CloseHandle(ProcInfo.hProcess);



Здесь я привёл не весь код, только отдельные участки.
Когда запускается приложение не на Java, всё работает.
Как только запускаются jar файлы, происходит следующее:
          первое скомпилированное приложение работает нормально
          начиная со второго приложение отказывается запускаться
Проблему решает код:
Код

 if (de.u.CreateProcessInfo.hFile!=NULL)
             CloseHandle(de.u.CreateProcessInfo.hFile);

Это срабатывает, если убрать строки:
Код

        HANDLE hJob=CreateJobObject(0,"");
        JOBOBJECT_EXTENDED_LIMIT_INFORMATION jl={};
        jl.BasicLimitInformation.LimitFlags=JOB_OBJECT_LIMIT_PROCESS_MEMORY;
        jl.ProcessMemoryLimit=mem;
        SetInformationJobObject(hJob,JobObjectExtendedLimitInformation,&jl,sizeof(jl));
        AssignProcessToJobObject(hJob,ProcInfo.hProcess);

Однако это меня не устраивает (контроль памяти нужен). Если вышеприведённый код присутствует, то при обработке кода:
Код

 if (de.u.CreateProcessInfo.hFile!=NULL)
             CloseHandle(de.u.CreateProcessInfo.hFile);

возникает ошибка External exception C0000008.
http://ipicture.ru/


Т.е. чтобы работала прога, нужно удаление image файла. Чтобы можно было удалить image файл, нужно убрать контроль памяти. Если убрать контроль памяти, прога не будет работать. Как мне быть?

Автор: korian 22.3.2008, 20:55
я сам хз, скажу некоторые соображения, которые появились при прочтения MSDN
я так понимаю de.u.CreateProcessInfo.hFile надо сохранять куда-нить в момент сообщения CREATE_PROCESS_DEBUG_EVENT.
потом оно может быть не действительно. и закрывать поидее надо до последнего ContinueDebugEvent()

Автор: dumb 23.3.2008, 22:53
Цитата(CPlusPlusFAN @  22.3.2008,  19:34 Найти цитируемый пост)
возникает ошибка External exception C0000008
перед тем, как использовать de.u в качестве CREATE_PROCESS_DEBUG_INFO, надо бы удостовериться, что de.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT.

Автор: CPlusPlusFAN 24.3.2008, 13:14
Цитата

перед тем, как использовать de.u в качестве CREATE_PROCESS_DEBUG_INFO, надо бы удостовериться, что de.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT



Уважаемый dumb, можно немного поподробней, а то я после PHP тяжело въезжаю.

Автор: dumb 25.3.2008, 13:18
примерно так:
Код

bool bSeenFirstBP = false;
...
            rs=WaitForDebugEvent(&de,wait)!=0;
            if (!rs)
                TerminateProcess(ProcInfo.hProcess,0);
            else
            {
                status=DBG_CONTINUE;
                switch (de.dwDebugEventCode)
                {
                  case EXIT_PROCESS_DEBUG_EVENT:
                    works=false;
                  break;
                  case EXCEPTION_DEBUG_EVENT:
                    //Ошибки
                    status=DBG_EXCEPTION_NOT_HANDLED;
                    if (!bSeenFirstBP && (de.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT))
                    {
                      status = DBG_CONTINUE;
                      bSeenFirstBP = true;
                    }
                  break;
                  case CREATE_PROCESS_DEBUG_EVENT:
                    if (de.u.CreateProcessInfo.hFile && de.u.CreateProcessInfo.hFile!=INVALID_HANDLE_VALUE)
                      CloseHandle(de.u.CreateProcessInfo.hFile);
                  break;
                }
                ContinueDebugEvent(de.dwProcessId,de.dwThreadId,status);
            }
...

Автор: CPlusPlusFAN 29.3.2008, 19:45
dumb, изменил, как ты сказал: снова External exception C0000008.

Код

if (de.u.CreateProcessInfo.hFile!=NULL&&
                        de.u.CreateProcessInfo.hFile!=INVALID_HANDLE_VALUE)
                        {
                            CloseHandle(de.u.CreateProcessInfo.hFile);
                            de.u.CreateProcessInfo.hFile=NULL;
                        }


Если убрать de.u.CreateProcessInfo.hFile=NULL; такая же лажа. smile 

Автор: dumb 29.3.2008, 22:57
нет, тут суть  не в самой проверке, а в том, что это действие должно производиться тогда, когда de.dwDebugEventCode равен именно CREATE_PROCESS_DEBUG_EVENT.

Автор: CPlusPlusFAN 31.3.2008, 15:04
Вот полный код.

Код

bool Process::LoadCommand(char *process,char *command,char *directory,
                          unsigned int wait,unsigned int mem,
                          unsigned int &res,bool exception,
                          CrashEnum &crash,int &memory)
{
    STARTUPINFO StartInfo;
    int flag=CREATE_NO_WINDOW;
    DEBUG_EVENT de;
    de.u.CreateProcessInfo.hFile=NULL;

    crash=SUCCESS;

    ZeroMemory(&StartInfo,sizeof(STARTUPINFO));
    StartInfo.cb=sizeof(STARTUPINFO);

    if (exception)
        flag|=DEBUG_PROCESS;

    CreateProcess(process,command,NULL,NULL,FALSE,
                  flag,
                  NULL,directory,&StartInfo,&ProcInfo)!=0;

    res=timeGetTime();
    if (!exception)
        WaitForSingleObject(ProcInfo.hProcess,wait);
    else
    {
        bool works=true,first=true,rs;
        DWORD status=DBG_CONTINUE;
        
        HANDLE hJob=CreateJobObject(0,"");
        JOBOBJECT_EXTENDED_LIMIT_INFORMATION jl={};
        jl.BasicLimitInformation.LimitFlags=JOB_OBJECT_LIMIT_PROCESS_MEMORY;
        jl.ProcessMemoryLimit=mem;
        SetInformationJobObject(hJob,JobObjectExtendedLimitInformation,&jl,sizeof(jl));
        AssignProcessToJobObject(hJob,ProcInfo.hProcess);

        while (works)
        {
            rs=WaitForDebugEvent(&de,wait)!=0;

            if (!rs)
                TerminateProcess(ProcInfo.hProcess,0);
            else
                if (de.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT)
                    works=false;
                else
                    if (de.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT)
                    {
                        if (de.u.CreateProcessInfo.hFile!=NULL&&
                        de.u.CreateProcessInfo.hFile!=INVALID_HANDLE_VALUE)
                        {
                            CloseHandle(de.u.CreateProcessInfo.hFile);
                            de.u.CreateProcessInfo.hFile=NULL;
                        }
                    }
                    else
                    if (de.dwDebugEventCode==EXCEPTION_DEBUG_EVENT)
                        switch (de.u.Exception.ExceptionRecord.ExceptionCode)
                        {
                            case EXCEPTION_ACCESS_VIOLATION:
                            {
                                crash=ACCESS_VIOLATION;
                                status=DBG_EXCEPTION_NOT_HANDLED;
                                TerminateProcess(ProcInfo.hProcess,0);
                            }
                            break;
                            case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
                            {
                                crash=ARRAY_OUT_OF_BOUNDS;
                                status=DBG_EXCEPTION_NOT_HANDLED;
                                TerminateProcess(ProcInfo.hProcess,0);
                            }
                            break;
                            case EXCEPTION_FLT_DIVIDE_BY_ZERO:
                            {
                                crash=FLOAT_DIV_BY_0;
                                status=DBG_EXCEPTION_NOT_HANDLED;
                                TerminateProcess(ProcInfo.hProcess,0);
                            }
                            break;
                            case EXCEPTION_FLT_OVERFLOW:
                            {
                                crash=FLOAT_OVERFLOW;
                                status=DBG_EXCEPTION_NOT_HANDLED;
                                TerminateProcess(ProcInfo.hProcess,0);
                            }
                            break;
                            case EXCEPTION_FLT_UNDERFLOW:
                            {
                                crash=FLOAT_UNDERFLOW;
                                status=DBG_EXCEPTION_NOT_HANDLED;
                                TerminateProcess(ProcInfo.hProcess,0);
                            }
                            break;
                            case EXCEPTION_INT_DIVIDE_BY_ZERO:
                            {
                                crash=INT_DIV_BY_0;
                                status=DBG_EXCEPTION_NOT_HANDLED;
                                TerminateProcess(ProcInfo.hProcess,0);
                            }
                            break;
                            case EXCEPTION_STACK_OVERFLOW:
                            {
                                crash=STACK_OVERFLOW;
                                status=DBG_EXCEPTION_NOT_HANDLED;
                                TerminateProcess(ProcInfo.hProcess,0);
                            }
                            break;
                            case EXCEPTION_BREAKPOINT:
                            {
                                if (first)
                                    first=false;
                                else
                                {
                                    status=DBG_EXCEPTION_NOT_HANDLED;
                                    crash=ACCESS_VIOLATION;
                                    TerminateProcess(ProcInfo.hProcess,0);
                                }
                            }
                            break;
                            default:
                            {
                                crash=MEMORY_EXCEEDED;
                                status=DBG_EXCEPTION_NOT_HANDLED;
                                memory=mem;
                                TerminateProcess(ProcInfo.hProcess,0);
                            }
                        }

                ContinueDebugEvent(de.dwProcessId,de.dwThreadId,status);
        }

        CloseHandle(hJob);
    }
    res=timeGetTime()-res;

    if (crash!=MEMORY_EXCEEDED)
    {
        PROCESS_MEMORY_COUNTERS coun;
        GetProcessMemoryInfo(ProcInfo.hProcess,&coun,sizeof(coun));
        memory=coun.PeakWorkingSetSize;
    }
    
    TerminateProcess(ProcInfo.hProcess,0);

    CloseHandle(ProcInfo.hThread);
    CloseHandle(ProcInfo.hProcess);

    return res<=wait;
}


Первый исходник компилится (с флагом exception==false) и работает на всех тестах. А второй компилится, но не запускается.

Автор: dumb 1.4.2008, 01:32
так как воспроизвести твои условия не представляется возможным, то тут только одна рекомендация: осваивай отладчик билдеровский. smile

код вроде выглядит вполне рабочим, с небольшими огрехами: не проверяется результат CreateProcess, упрощенная схема пропуска первого системного брекпоинта(там, где флаг first) предполагает отладку только одного процесса(т.е. flag|=DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;) и перед WaitForDebugEvent неплохо бы сделать status=DBG_CONTINUE.

Автор: CPlusPlusFAN 8.4.2008, 16:37
В общем такие дела:
Программы на Java работают, но иногда. Например код:
Код

import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.util.Scanner;

public class Unit
{
    public static void main(String[] args)
    {
        try
        {    
            Scanner inp=new Scanner(new FileInputStream("input.txt"));
            BufferedWriter outp=new BufferedWriter(new FileWriter("output.txt"));
        
            outp.close();
            inp.close();
        }
        catch(Exception e)
        {}
    }
}

работает и не вызывает проблем.
А вот код:
Код

import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.util.Scanner;

public class Unit
{
    public static void main(String[] args)
    {
        try
        {    
            Scanner inp=new Scanner(new FileInputStream("input.txt"));
            BufferedWriter outp=new BufferedWriter(new FileWriter("output.txt"));
            
            int N;
            
            N=inp.nextInt();
            outp.write(String.format("%d ",N));
        
            outp.close();
            inp.close();
        }
        catch(Exception e)
        {}
    }
}

выдаёт ошибку, описанную выше. Т.е. при чтении/записи что-то происходит.

Трассировка показала, что на строке:
Код

rs=WaitForDebugEvent(&de,wait)!=0;


, когда она выполняется второй раз, переменная:
Код

de.u.CreateProcessInfo.hProcess


принимает какое-то левое значение, а переменная:
Код

de.u.CreateProcessInfo.hThread


становится равной NULL. Что происходит?

ЗЫ Если не выполнять:
Код

AssignProcessToJobObject(hJob,ProcInfo.hProcess);


, то эти проблемы отпадают.

Автор: dumb 9.4.2008, 01:24
прочитай, пожалуйста, что-нибудь(http://users.msu.dubna.ru/~ovg/c++course/p1-7.html) про union(объединение).

Цитата(CPlusPlusFAN @  8.4.2008,  17:37 Найти цитируемый пост)
Что происходит?
еще раз повторю: переменные de.u.CreateProcessInfo.* имеют смысл только в тот момент, когда de.dwDebugEventCode равен CREATE_PROCESS_DEBUG_EVENT.

hint: если выложишь тестовый проект + java-прогу(на которой выходит ошибка), может кто-нибудь поможет. я наверное не смогу, т.к. сижу на чумоданах... smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)