Erros, bugs, perguntas - página 2725

 
Vict:

Acha que a sua Sharp apareceu num campo limpo? Enraizada em C, a estrutura é um recipiente estúpido sem açúcar extra.

Bem, o homem evoluiu de um macaco. Mas isso não significa que o homem é um macaco burro "sem qualquer açúcar extra", pois não? ) Já expliquei que de facto estruturas MQL = estruturas C#, com uma pequena diferença: em C# ainda podem implementar interfaces. interfaces, Carl! )

Como pode ter tanta certeza? Chamar uma função a partir de outra unidade de tradução/outro módulo/ciclos/compilador desafinado/... . Não sobrestimar as capacidades do optimizador. Isto não é uma optimização de Copy elision que os compiladores são obrigados a fazer. Se os optimizadores se tornarem tão inteligentes e deixarem de custar qualquer coisa, escreverão no próximo padrão C: "a inicialização por defeito não deixa um objecto em estado indefinido".

Porque é a coisa mais trivial e primitiva a que nem sequer se pode chamar optimização. Penso que todos os compiladores o fazem por defeito, mesmo em Debug-mode. O que pode ser mais fácil? Durante a análise do código, é necessário rastrear o acesso às variáveis. Se houver uma operação de escrita repetida e não houve nenhuma operação de leitura, então corta-se a entrada anterior.

Pode ignorá-lo, mas depois não se surpreenda que codificadores decentes o vejam como um codificador de merda quando virem as suas estruturas recheadas de funções

Qual é a principal qualidade que um programa de computador deve possuir? Estabilidade. Com os mesmos dados de entrada deve dar resultados imutáveis. E propõe-se esquecê-lo. Algures esqueceu-se de inicializar uma variável, algures adicionou um novo campo à estrutura que ficou por inicializar em todo o programa, e o programa continuou. O programa funciona desta e daquela maneira...

A linguagem C foi criada num passado distante quando as capacidades de hardware eram muito fracas, pelo que grande parte do trabalho de optimização foi deixado ao programador. Se tem tanta comichão, porque se refere a C e não Assembler, por exemplo? Codifique os sistemas de negociação em Assembler. Tenho a certeza de que serão os mais rápidos, talvez mesmo à frente do mercado )

 
Alexey Navoykov:

Porque é a coisa mais trivial e primitiva, a que dificilmente se pode chamar optimização. Penso que todos os compiladores o fazem por defeito mesmo em Debug-mode. O que poderia ser mais fácil? Enquanto analisam o código, monitorizam o acesso às variáveis. Se houver uma operação de escrita repetida e não houve nenhuma operação de leitura, então corta-se a entrada anterior.

Se o programa fosse completamente previsível em tempo de compilação, não teria de ser executado em tempo de execução. Deve, por definição, tirar algo do mundo exterior e produzir um resultado com base nele, e essa é a incerteza que se interpõe no caminho do optimizador. Outro segredo - as bibliotecas partilhadas estão ligadas à aplicação em tempo de execução, o optimizador não consegue localizar nada lá. Há mais um milhão de casos a serem expulsos. (Um milhão, Karl!)

Em algum lugar esqueci-me de inicializar uma variável ou adicionei um novo campo a uma estrutura que ficou por iniciar em todo o programa, e o programa prossegue. O programa funciona desta e daquela maneira...

Em algum lugar multiplicei por 2 em vez de 3, chamado fn() em vez de fn_(), ... . Se as suas mãos estão erradas, está em apuros.

A linguagem C foi criada há muito tempo quando as capacidades de hardware eram muito fracas, por isso muito do trabalho de optimização foi deixado ao programador. Se está ansioso por o fazer, porque se refere ao C e não ao Assembler? Codifique os sistemas de negociação em Assembler. Tenho a certeza que serão os mais rápidos, talvez mesmo à frente do mercado.

para sua referência: normas C (as mais recentes, não são normas C++): C11, C18, C2x está a ser preparado. Em vez disso, escreveu isto como resultado de incompetência.
 
Vict:

Se o programa fosse completamente previsível em tempo de compilação, não precisaria de ser executado em tempo de execução. Por definição, deve tirar algo do mundo exterior e produzir um resultado com base nele, e esta é uma incerteza que impede o optimizador. Outro segredo - as bibliotecas partilhadas estão ligadas à aplicação em tempo de execução, o optimizador não consegue localizar nada lá. Há mais um milhão de casos a serem expulsos. Um milhão, Karl!)

Ointercâmbio de dados com o mundo exterior são casos especiais e requerem soluções especiais. Estamos a falar de programação como tal e dos casos em que o compilador tem a garantia de saber que a variável não é controlada a partir do exterior. E esta deve ser a grande maioria dos casos. Caso contrário, tem uma programação puramente de sistema, o que é realmente melhor fazer em C, ou ainda melhor - em assembler.

Algures multiplicado por 2 em vez de 3, chamado fn() em vez de fn_(), . . Se as suas mãos estiverem tortas, problemas.

Se multiplicar por 2 em vez de 3, obtém um erro estável no programa que é fácil de diagnosticar e encontrar. E se a variável não for inicializada obtém algo que funciona agora e depois não, de vez em quando, com consequências imprevisíveis. Em geral, é bastante estranho que vos explique estas noções básicas, fazendo-me passar por um programador experiente.

 
Alexey Navoykov:

Intercâmbio de dados com o mundo exterior - estes são casos especiais, e requerem soluções especiais. Mas estamos a falar de programação como tal, e dos casos em que o compilador tem a garantia de saber que a variável não é controlada a partir do exterior. E esta deve ser a grande maioria dos casos. Caso contrário, obtém-se uma programação puramente do sistema, o que é realmente melhor fazer em C, ou ainda melhor - em assembler.

A comunicação com o mundo exterior é uma parte essencial de qualquer programa. Deixe-me repetir - caso contrário pode ser descoberto em tempo de compilação. Por exemplo, será que o compilador vai cortar a inicialização aqui?

int i = 54;
if (read_socket() == SIGNAL) {
   fn(i);
}
i = 100;
...

// естественно, что никто не пишет такой бред:
int q = 3;
q = 7;
q = 9;
fq(q);

Obviamente, não faz ideia do que read_socket() irá regressar. O programa inteiro é "permeado" pela interacção com o mundo exterior. + adicionar aqui uma chamada a módulos externos... .

Se o multiplicar por 2 em vez de 3, obtém-se um erro estável no programa que é fácil de diagnosticar e encontrar. E com uma variável não-inicializada obtém-se algo que funciona de vez em quando, com consequências imprevisíveis. Na verdade, é bastante estranho que eu vos explique estas noções básicas, que se fazem passar por programadores experientes.

Se quiser obter um erro estável, é muito simples inicializar a pilha:

int main() {
    if (true)
        int init_stack[10000] {0};
}

Inicializar a memória do HIP é também canja. Se nos depararmos com alguma armadilha de representação, obteremos uma lixeira de núcleo.

Mais uma vez, se os optimizadores fossem muito espertos, eles iriam equiparar o init padrão com o init de valor com a inserção de instruções inicializadoras pelo compilador, conforme necessário ainda em alguns C11, mas infelizmente. Ninguém força, se não quiser, fazer T val{}; Cansado de explicar coisas elementares.

 
Vict:

Mais uma vez, se os optimizadores fossem muito espertos, eles iriam equiparar o init padrão com o init de valor com a inserção de instruções de inicialização do compilador conforme necessário em alguns C11, mas infelizmente. Ninguém obriga, se não o quiser, a fazer T val{}; Cansado de explicar coisas elementares.

Porque, tal como o entendo, a norma C++ descreve as regras muito formalmente, sem contextualização, ou seja, inicialização sempre ou nunca. Para comparação, em C# pode declarar uma variável sem inicialização, mas mais adiante no código ela deve ser necessariamente inicializada. Ou seja, o compilador analisa o código que se segue e não apenas o comando actual. Isto está estabelecido nas regras linguísticas. Mas a norma não prevê qualquer análise em C++. Portanto, se forçarem a inicialização, queixar-se-ão de que eu próprio quero controlar e inicializar tudo! )

 
Alexey Navoykov:

Porque a norma C++, tal como a entendo, descreve as regras muito formalmente, sem contextualização, ou seja, a inicialização é sempre ou nunca. Em comparação, em C# pode declarar uma variável sem inicialização, mas mais adiante no código ela deve ser necessariamente inicializada. Ou seja, o compilador analisa o código que se segue e não apenas o comando actual. Isto está estabelecido nas regras linguísticas. Mas a norma não prevê qualquer análise em C++. Portanto, se forçarem a inicialização, queixar-se-ão de que eu próprio quero controlar e inicializar tudo! )

É que há soluções testadas, e se funcionar fora da caixa, muitas vezes causando despesas gerais desnecessárias, então ninguém a incluirá. Por exemplo, prescreveram na norma um MUST para o compilador fazer elisão de cópia em c++17.

 

O tema chama-se "Insectos, insectos, perguntas".

Por favor, crie um tópico onde irá discutir MQL vs C#,C++, e outras coisas relacionadas com sintaxe, compiladores e exercícios mentais.

Está a desperdiçar o fio, e outras questões e mensagens dos utilizadores estão a afogar-se na sua discussão.

Perguntam-me onde fazer uma pergunta - sou dirigido aqui e a resposta é: "Os tios estão a discutir por uma centena de páginas ali, por isso não vou interferir, o resto não faz sentido ...

 
const int DEFAULT_INT_VALUE   = 147;
input int thisIsAnInput       = DEFAULT_INT_VALUE;
'NoConstForInput.mq5' NoConstForInput.mq5 1 1
'DEFAULT_INT_VALUE' - constante esperado NoConstForInput.mq5 13 33
1 erros, 0 avisos 2 1

Construir 2361 e 2390

 
Alain Verleyen:
'NoConstForInput.mq5' NoConstForInput.mq5 1 1
'DEFAULT_INT_VALUE' - constante esperado NoConstForInput.mq5 13 33
1 erros, 0 avisos 2 1

Construir 2361 e 2390

#define  DEFAULT_INT_VALUE 147
 
Vict:

Olhe, se quiser obter um erro estável, inicializar a pilha é muito fácil:

Inicializar a memória de um HIP é também canja. Se nos depararmos com alguma armadilha de representação, obtemos uma lixeira de núcleo no seu todo.

Um último comentário, por favor não se zangue com os moderadores ))).

Preciso de esclarecer porque é que a pilha tem valores diferentes de chamada para chamada. Trata-se de proteger https://ru.wikipedia.org/wiki/ASLR, e nem sequer é preciso inanalisar nada, como já disse anteriormente. No meu caso - executo o software sob gdb (debugger), que o colocará no mesmo endereço sempre que for executado, ou seja, a pilha não será contaminada por endereços de retorno "aleatórios".