Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

CreateProcess, WaitForMultipleObjects и ошибка

7.0K
26 июля 2009 года
Rusd
88 / / 26.08.2006
Доброго всем времени суток.
Имеется консольная программа.
Суть программы:
CreateProcess вызывает ещё один или несколько экземпляров программы, но с другим параметром, которые в свою очередь только и делают, что просто занимают память и ждут некоторое время.
Ошибка вылетает на этапе, когда "дочерние" процессы заканчивают работу. Причем, судя по тому, что количество окон с предложением "отправить отчет об ошибке" соответствует количеству "дочерних" процессов, ошибка закралась где-то в них. А отладчик VS2008 скромно молчит, т.к. "родительский" процесс завершает работу без ошибок.

Код:
Код:
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <windows.h>

const int iParams = 3;
const int iWorkTimeDef = 5000;
const int iMemSizeDef = 10;
const int iMemSizeMax = 1024;

int iMemSize = iMemSizeDef;
int iWorkTime = iWorkTimeDef;
bool bChild = false;
char *cParams[] = {"-ms","-mb","-take"};
int *iBuf = NULL;


bool InterpretParams(int argc, char *argv[])
{
    int j;
    if (argc == 1) return true;
    for (int i = 1; i < argc; i = i+2)
    {
        j = 0;
        while ((strcmp(argv,cParams[j])!=0) && (j<iParams))j++;
        switch (j)
        {
            case 0: //-ms
                if ((i+1 >= argc) || !(iWorkTime = atoi(argv[i+1])))
                {
                    printf("Wrong argument in %s key\n",cParams[j]);
                    iWorkTime = iWorkTimeDef;
                }
                break;
            case 1: //-mb
                if ((i+1 >= argc) || !(iMemSize = atoi(argv[i+1])))
                {
                    printf("Wrong argument in %s key\n",cParams[j]);
                    iMemSize = iMemSizeDef;
                }
                break;
            case 2: //-take
                bChild = true;
                if ((i+2 >= argc) || !(iMemSize = atoi(argv[i+1])) || !(iWorkTime = atoi(argv[i+2])))
                {
                    printf("Wrong arguments in %s key\n",cParams[j]);
                    return false;
                }
                printf("Requesting %d MB memory.\n",iMemSize);
                iBuf = (int *) malloc(iMemSize*1024*1024);
                printf("Going to sleep\n");
                Sleep(iWorkTime);
                printf("Going to free memory\n");
                free(iBuf);
                break;
            default:
                printf("Unknown parameter: %s\n",argv);
                return false;
        }
    }
    return true;
}

int main(int argc, char* argv[], char* env[])
{
    char cCom[1024] = "\"";
    char cComBuf[1024] = "";
    int i = 0;
    HANDLE* pHandle;
    STARTUPINFOA sInf;
    PROCESS_INFORMATION* pInf;
    int iChild;
    strcat(cCom,argv[0]);
    strcat(cCom,"\" -take ");
    if (!InterpretParams(argc,argv))
    {
        printf("Halt.\n");
        getch();
        return 1;
    }
    if (bChild)
    {
        printf("Child process fin.\n");
        return 1;
    }
    iChild = iMemSize/iMemSizeMax + 1;
    ZeroMemory(&sInf,sizeof(STARTUPINFO));
    sInf.cb = sizeof(sInf);
    pInf = (PROCESS_INFORMATION*) malloc(iChild*sizeof(PROCESS_INFORMATION));
    if (pInf == NULL)
    {
        printf("Can't allocate memory for process information\n");
        return 1;
    }
    ZeroMemory(pInf,iChild*sizeof(pInf));
    pHandle = (HANDLE*) malloc(iChild*sizeof(HANDLE));
    if (pHandle == NULL)
    {
        printf("Can't allocate memory for handles\n");
        free(pInf);
        return 1;
    }
    printf("Creating %d processes for %d ms\n",iChild,iWorkTime);
    while (iMemSize / iMemSizeMax >= 1)
    {
        strcpy(cComBuf,cCom);
        sprintf(&cComBuf[strlen(cComBuf)],"%d %d",iMemSizeMax,iWorkTime);
        iMemSize = iMemSize - iMemSizeMax;
        if (!CreateProcessA(    NULL, cComBuf,
                            NULL, NULL,
                            false,0,
                            NULL, NULL,
                            &sInf,&pInf))
        {
            iChild = i+1;
            printf("Can't create process #%d\n",i);
            iMemSize = -1;
        };
        pHandle = pInf.hProcess;
        i++;
    }
    if (iMemSize > 0)
    {
        strcpy(cComBuf,cCom);
        sprintf(&cComBuf[strlen(cComBuf)],"%d %d",iMemSize,iWorkTime);
        CreateProcessA( NULL, cComBuf,
                        NULL, NULL,
                        true,0,
                        NULL, NULL,
                        &sInf,&pInf);
        pHandle = pInf.hProcess;
    }
    printf("Waiting.\n");
    WaitForMultipleObjects(iChild,pHandle,true,INFINITE);
    printf("Closing handles\n");
    for (i=0; i<iChild; i++)
    {
        CloseHandle(pInf.hProcess);
        CloseHandle(pInf.hThread);
    }
    return 1;
}
288
27 июля 2009 года
nikitozz
1.2K / / 09.03.2007
Пока еще не разбирался в коде, но сразу вопрос - пробовали запускать в отладчике процесс с этими "другими" параметрами?
288
27 июля 2009 года
nikitozz
1.2K / / 09.03.2007
Дошли таки руки.
Во-первых, при запуске дочернего процесса вы передаете параметр как ' -take' (с пробелом в начале), а проверяете на '-take' (без пробела), так что условие
 
Код:
(strcmp(argv,cParams[j])!=0)

никогда не будет true.
Во-вторых, если хотите задать именно такое условие
 
Код:
((strcmp(argv,cParams[j])!=0) && (j<iParams))
,
то его надо делать так
 
Код:
( (j<iParams) && (strcmp(argv,cParams[j])!=0) )


Дальше этого места код не смотрел.
7.0K
27 июля 2009 года
Rusd
88 / / 26.08.2006
Спасибо, nikitozz, что выделили время.

Цитата: nikitozz

Во-первых, при запуске дочернего процесса вы передаете параметр как ' -take' (с пробелом в начале), а проверяете на '-take' (без пробела), так что условие
 
Код:
(strcmp(argv,cParams[j])!=0)

никогда не будет true.


Строка формируется вида: "<путь>" -take <val1> <val2>
И пробел тут к месту, иначе -take мы не найдем в массиве argv[] - а там он лежит как раз в виде "-take" (без пробела).

Цитата: nikitozz

Во-вторых, если хотите задать именно такое условие
 
Код:
((strcmp(argv,cParams[j])!=0) && (j<iParams))
,
то его надо делать так
 
Код:
( (j<iParams) && (strcmp(argv,cParams[j])!=0) )


Да, действительно :) проглядел - угроза обращения за пределы массива.

Ошибка была решена, добавлением одной строки: i++
в case 2 после free(iBuf)

7
27 июля 2009 года
@pixo $oft
3.4K / / 20.09.2006
Извините,что не совсем в тему,но хотелось бы узнать вот что
Цитата: nikitozz
Во-вторых, если хотите задать именно такое условие
 
Код:
((strcmp(argv,cParams[j])!=0) && (j<iParams))
,то его надо делать так
 
Код:
( (j<iParams) && (strcmp(argv,cParams[j])!=0) )

Каково различие в этих кодах?Ведь по сути это одно и тоже,только с разным порядком?Или дело в том,что,проверив 1е условие во 2м случае и найдя его равным False,проверка дальше не пойдёт?

260
27 июля 2009 года
Ramon
1.1K / / 16.08.2003
Цитата: @pixo $oft
Извините,что не совсем в тему,но хотелось бы узнать вот чтоКаково различие в этих кодах?Ведь по сути это одно и тоже,только с разным порядком?Или [COLOR="Red"]дело в том,что,проверив 1е условие во 2м случае и найдя его равным False,проверка дальше не пойдёт[/COLOR]?



Именно так.

288
28 июля 2009 года
nikitozz
1.2K / / 09.03.2007
Цитата: @pixo $oft
Извините,что не совсем в тему,но хотелось бы узнать вот чтоКаково различие в этих кодах?Ведь по сути это одно и тоже,только с разным порядком?Или дело в том,что,проверив 1е условие во 2м случае и найдя его равным False,проверка дальше не пойдёт?



В том то и вся суть :)
Ведь cParams массив из 3 элементов. Так что если мы сначала не проверим, что j < 3, то получим cParams[3].

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог