Pergunta

Esta é uma pergunta bastante iniciante que deve ser responsável razoavelmente rapidamente ...

Basicamente, após a primeira chamada para Printf dentro eco, o conteúdo de args está corrompido. Parece -me que estou passando as dicas incorretamente. Mas não consegue descobrir por quê?

#define MAX_PRINT_OUTPUT 4096

void Echo(char *args[MAX_COMMAND_ARGUMENTS], int argCount)
{
    for (int i = 1; i < argCount; ++i)
    {
        Printf("%s ", args[i]);
        Printf("\n");
    }
};

void Printf(const char *output, ...)
{
    va_list args;
    char formattedOutput[MAX_PRINT_OUTPUT];

    va_start(args, output);
    vsnprintf(formattedOutput, sizeof(formattedOutput), output, args);
    va_end(args);

    g_PlatformDevice->Print(formattedOutput);
};

void RiseWindows::Print(const char *output)
{
    //Corruption appears to occur as soon as this function is entered
    #define CONSOLE_OUTPUT_SIZE 32767

    char buffer[CONSOLE_OUTPUT_SIZE];
    char *pBuffer = buffer;
    const char *pOutput = output;
    int i = 0;

    while (pOutput[i] && ((pBuffer - buffer) < sizeof(buffer) - 1))
    {
        if (pOutput[i] == '\n' && pOutput[i+1] == '\r' )
        {
            pBuffer[0] = '\r';
            pBuffer[1] = '\n';
            pBuffer += 2;
            ++i;
        }
        else if (pOutput[i] == '\r')
        {
            pBuffer[0] = '\r';
            pBuffer[1] = '\n';
            pBuffer += 2;
        }
        else if (pOutput[i] == '\n')
        {
            pBuffer[0] = '\r';
            pBuffer[1] = '\n';
            pBuffer += 2;
        }
        else
        {
            *pBuffer = pOutput[i];
            ++pBuffer;
        }
        ++i;
    }
    *pBuffer = 0;

    SendMessage(this->ConsoleWindow.hwndBuffer, EM_LINESCROLL, 0, 0xffff);
    SendMessage(this->ConsoleWindow.hwndBuffer, EM_SCROLLCARET, 0, 0);
    SendMessage(this->ConsoleWindow.hwndBuffer, EM_REPLACESEL, 0, (LPARAM)buffer);

};

NOTA Este não é um código de produção, apenas prova de conceito.
EDITAR g_platformDevice é do tipo RiseWindows, se isso não estava claro ...
EDITAR Isso está em uma plataforma Windows XP em execução em vs2008

ATUALIZARPara qualquer pessoa interessada, o problema parece ter sido uma pilha de chamadas transbordada, mais abaixo na pilha, então essa outra grande matriz estava sendo definida. Refatorando isso eliminou a corrupção da memória. Então, atingiu o empilhamento de agressão!

Foi útil?

Solução

Você não mencionou em qual ambiente esse código é executado. Pode ser que você esteja soprando sua pilha. Você está declarando uma matriz de 32767 bytes na pilha em RiseWindows :: Print. Em alguns ambientes de sistema incorporados com os quais estou familiarizado com isso, seria uma má notícia. Você pode aumentar o tamanho da pilha e/ou alocar esse buffer na pilha apenas para testar essa teoria? Você pode querer fazer com que esse buffer um vetor de std ::, ou possivelmente, um vetor de membro privado para evitar alocá -lo e realocá -lo toda vez que você ligar para a impressão.

Nesse sentido, qual o tamanho do max_print_output?

Outras dicas

Provavelmente não é o bug que você está perguntando, mas no seu loop você é o duplo incremento pbuffer em alguns casos, o que pode estar empurrando você no final do buffer, porque você só verifica o comprimento-1 (para terminação nula).

Presidente aleatório: tenho a sensação de que o problema é causado por esta linha no printf:

char formattedOutput[MAX_PRINT_OUTPUT];

A razão pela qual acho que isso é porque você tem alguns indicadores obviamente declarados e alguns indicados obviamente indicados. Uma variedade de chars é um ponteiro - de maneira alguma, mas não é óbvio. Na definição de função de eco args é definida como uma matriz bidimensional porque você a tem como

*args[MAX_COMMAND_ARGS]

Você quer isso? Meu palpite é que algo está sendo aprovado sem intenção como uma referência em vez de um valor, porque o que é um ponteiro vs. matriz é vagamente definido e você está passando um ponteiro para um ponteiro que é o início de uma matriz em vez de um ponteiro que é o início de uma matriz. Como você disse que é corrompido quando você entra no RiseWindows :: Imprima meu palpite é que você está passando a coisa errada.

Além disso, um ponteiro const para um char preserva apenas o valor do ponteiro, até onde eu sei, não o valor do conteúdo no ponteiro.

Você tentou a estratégia de divisão e conquista?

  • Comece a comentar as linhas até que funcione.
  • Uma vez que funcione corretamente as linhas de descomamento até você pressionar onde está o erro.

Observe a memória apontada por args [] na janela separada enquanto você passo a passo também pode ser útil.

Posso sugerir passar com um depurador para ver onde o código corrompe?

while (Poutput [i] && ((pbuffer - buffer) <sizeof (buffer) - 1))

mudar para:

while (Poutput [i] && ((pbuffer - buffer) <sizeof (buffer) - 2))

Você está escrevendo 2 caracteres por vez, então precisa ter espaço para dois caracteres.

Não tenho certeza se é como deve funcionar ou não, mas o eco não impede o primeiro elemento de args

// Changed i=1 to i=0;
for (int i = 0; i < argCount; ++i)
{
    Printf("%s ", args[i]);
    Printf("\n");
}

Você deseja mover seu #Define da chamada de função para o topo do arquivo:

As diretivas de pré -processador podem aparecer em qualquer lugar em um arquivo de origem, mas se aplicam apenas ao restante do arquivo de origem.

Provavelmente, isso não está causando a corrupção neste caso, mas não é padrão e pode facilmente causar problemas na linha.

A teoria do trabalho é que estamos soprando a pilha com:

char buffer [console_output_size]; char *pbuffer = buffer;

Em vez disso, tente:

char *pbuffer = novo char [console_output_size];

E depois lembre -se de ligar para excluir [] pbuffer no final.

Eu realmente não investigei isso, mas você tem seus tipos confusos ... isso é extremamente pedante, mas faz a diferença em C.

Aqui, você tem uma única variedade de char.

char formattedOutput[MAX_PRINT_OUTPUT];

E aqui, você tem uma função que espera um ponteiro const Char.

void RiseWindows::Print(const char *output)

Tentar:

void RiseWindows::Print(const char output[])

Além disso, percebo que você está modificando a memória nesses buffers - tem certeza de que pode fazer isso? No mínimo, tenho certeza de que você não pode usar arbitUamente mais sem alocar mais memória. (Dica dica!)

Eu alocaria minha própria matriz e copiaria a string nela. Eu usaria funções de string para substituir as linhas de novo conforme aplicável.

Finalmente, sugiro fortemente que você use a string std :: aqui. (Embora você não consiga colocá -los nas coisas de varargs - você terá que usar as cordas C para elas, mas copie -as de volta para STD :: String's quando puder).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top