sprintf() и WriteFile(), влияющие на строковый буфер

У меня очень странная проблема, которую я не могу понять. К сожалению, я даже не уверен, как это описать, не описав всего моего приложения. Я пытаюсь сделать следующее:

1) read a byte from the serial port
2) store each char into tagBuffer as they are read
3) run a query using tagBuffer to see what type of tag it is (book or shelf tag)
4) depending on the type of tag, output a series of bytes corresponding to the type of tag

Большая часть моего кода реализована, и я могу получить правильный код тега, отправленный обратно через последовательный порт. Но есть две строки, которые я добавил в качестве операторов отладки, и когда я попытался их удалить, моя программа перестала работать.

The lines are the two lines at the very bottom:

    sprintf(buf,"%s!\n", tagBuffer);
    WriteFile(hSerial,buf,strlen(buf), &dwBytesWritten,&ovWrite);

Если я попытаюсь удалить их, «tagBuffer» сохранит только последний символ, а не буфер. То же самое со следующей строкой, WriteFile().

Я думал, что sprintf и WriteFile являются функциями ввода-вывода и не будут влиять на переменные. Я застрял, и мне нужна помощь, чтобы исправить это.

//keep polling as long as stop character '-' is not read
while(szRxChar != '-')
{
    // Check if a read is outstanding
    if (HasOverlappedIoCompleted(&ovRead))
    {
        // Issue a serial port read
        if (!ReadFile(hSerial,&szRxChar,1,
                &dwBytesRead,&ovRead))
        {
            DWORD dwErr = GetLastError();
            if (dwErr!=ERROR_IO_PENDING)
                return dwErr;
        }
    }

    // resets tagBuffer in case tagBuffer is out of sync
    time_t t_time = time(0);
    char buf[50];
    if (HasOverlappedIoCompleted(&ovWrite))
    {
        i=0;                                       
    }

    // Wait 5 seconds for serial input
    if (!(HasOverlappedIoCompleted(&ovRead)))
    {
        WaitForSingleObject(hReadEvent,RESET_TIME);
    }

    // Check if serial input has arrived
    if (GetOverlappedResult(hSerial,&ovRead,
            &dwBytesRead,FALSE))
    {
        // Wait for the write
        GetOverlappedResult(hSerial,&ovWrite,
            &dwBytesWritten,TRUE);

        if( strlen(tagBuffer) >= PACKET_LENGTH )
        {
            i = 0;
        }

        //load tagBuffer with byte stream
        tagBuffer[i] = szRxChar;
        i++;
        tagBuffer[i] = 0; //char arrays are \0 terminated

        //run query with tagBuffer  
        sprintf(query,"select type from rfid where rfidnum=\"");
        strcat(query, tagBuffer);
        strcat(query, "\"");
        mysql_real_query(&mysql,query,(unsigned int)strlen(query));

        //process result and send back to handheld
        res = mysql_use_result(&mysql);
        while(row = mysql_fetch_row(res))
        {
           printf("result of query is %s\n",row[0]);

           string str = "";
           str = string(row[0]);

           if( str == "book" )
           {
               WriteFile(hSerial,BOOK_INDICATOR,strlen(BOOK_INDICATOR),
                &dwBytesWritten,&ovWrite);
           }
           else if ( str == "shelf" )
           {
               WriteFile(hSerial,SHELF_INDICATOR,strlen(SHELF_INDICATOR),
                &dwBytesWritten,&ovWrite);
           }
           else //this else doesn't work
           {
               WriteFile(hSerial,NOK,strlen(NOK),
                &dwBytesWritten,&ovWrite);
           }
        }


        mysql_free_result(res);

        // Display a response to input
        //printf("query is %s!\n", query);
        //printf("strlen(tagBuffer) is %d!\n", strlen(tagBuffer));

        //without these, tagBuffer only holds the last character
        sprintf(buf,"%s!\n", tagBuffer);
        WriteFile(hSerial,buf,strlen(buf), &dwBytesWritten,&ovWrite);

    }
}

С этими двумя строками мой вывод выглядит следующим образом: s sh shel полка полка0 полка00 КОД КНИГИ полка0001

Без них я понял, что tagBuffer и buf хранят только самый последний символ в любой момент времени.

Любая помощь вообще будет принята с благодарностью. Спасибо.


person Steve    schedule 09.11.2008    source источник
comment
Где и как вы определяете tagBuffer?   -  person Jason Coco    schedule 09.11.2008
comment
char tagBuffer[8]; // содержит идентификатор тега int i=0; //индекс для tagBuffer   -  person Steve    schedule 09.11.2008
comment
хорошо, если ваш вывод правильный, то вы определенно переполняете tagBuffer... если вы измените его на tagBuffer[32] (или какое-то другое большое число) и закомментируете эти строки, будет ли это работать так, как ожидалось?   -  person Jason Coco    schedule 09.11.2008
comment
С 32 я получаю tagBuffer = (самый последний символ), в то время как buf - мусор согласно стандартному выводу   -  person Steve    schedule 09.11.2008


Ответы (4)


Где вы выделяете tagbuffer, насколько он велик?
Возможно, вы перезаписываете 'buf', потому что пишете за концом tagbuffer.

person Martin Beckett    schedule 09.11.2008

Кажется маловероятным, что эти две строки окажут такое влияние на правильную программу - может быть, вы не выделили достаточно места в buf для всей длины строки в tagBuffer? Это может вызвать переполнение буфера, скрывающее реальную проблему?

person 1800 INFORMATION    schedule 09.11.2008

Первое, что я хотел бы сказать, это общий совет: ошибки не всегда там, где вы думаете. Если у вас происходит что-то, что кажется бессмысленным, это часто означает, что ваши предположения где-то в другом месте неверны.

Здесь кажется очень маловероятным, что sprintf() и WriteFile() изменят состояние переменной массива "buf". Однако эти две строки тестового кода записывают в «hSerial», в то время как ваш основной цикл также читает из «hSerial». Это звучит как рецепт для изменения поведения вашей программы.

Предложение: Измените строки вывода отладки, чтобы они сохранялись в другом месте: в диалоговом окне, в файле журнала и т. п. Выходные данные отладки, как правило, не должны направляться в файлы, используемые в основной логике, так как это слишком вероятно изменит поведение основной логики.

person DavidK    schedule 09.11.2008
comment
Спасибо за совет. Я удалил эти строки и вывел их на стандартный вывод Вот что я получил: buf is ! tagBuffer — это s! буф есть! tagBuffer - это h! буф есть! tagBuffer — это e! буф есть! tagBuffer — это l! буф есть! tagBuffer - это f! буф есть! tagBuffer равен 0! буф есть! tagBuffer равен 0! буф есть! tagBuffer равен 1! - person Steve; 09.11.2008
comment
Похоже, buf ничего не хранит - person Steve; 09.11.2008
comment
Я бы также предложил добавить ведение журнала в стандартный вывод во всех случаях, когда ваша индексирующая переменная «i» сбрасывается до нуля. Запускается ли один из этих случаев для каждого прочитанного символа? - person DavidK; 09.11.2008

На мой взгляд, реальная проблема заключается в том, что вы пытаетесь читать и записывать последовательный порт из одного потока, и это делает код более сложным, чем он должен быть. Я предлагаю вам прочитать следующие статьи и пересмотреть свой дизайн:

В многопоточной реализации всякий раз, когда поток чтения читает сообщение из последовательного порта, вы затем отправляете его в основной поток вашего приложения. Затем основной поток будет анализировать сообщение и запрашивать базу данных, а затем ставить в очередь соответствующий ответ потоку записи.

Это может показаться более сложным, чем ваш текущий дизайн, но на самом деле это не так, как объясняет Новичок.

Надеюсь, это поможет!

person ChrisN    schedule 09.11.2008