Portal SAMP
[Ajuda] compilador - Versão de Impressão

+- Portal SAMP (https://portalsamp.com)
+-- Fórum: SA-MP (https://portalsamp.com/forumdisplay.php?fid=5)
+--- Fórum: Área de suporte (https://portalsamp.com/forumdisplay.php?fid=6)
+--- Tópico: [Ajuda] compilador (/showthread.php?tid=3959)



compilador - Mist - 11/09/2023

opa boa noite eu uso sublime text 3 como ide nao estava dando isto ao compilar alguem saber oque isso e como se resolver?

Tamanho do cabeçalho: 11404 bytes
Tamanho do código: 405820 bytes
Tamanho dos dados: 4040016 bytes
Tamanho da pilha/heap: 16.384 bytes; máximo estimado uso = 4.809 células (19.236 bytes)
Requisitos totais: 4473624 bytes


ja deixa traduzido!


RE: compilador - White_Blue - 11/09/2023

São informações da compilação, normalmente não são preocupantes.

Caso queira desativar, tire o -d3 das opções do compilador, pois essa opção é para que o compilador mostre informações de debug, como Header Size, Stack/Heap size, Data size.


RE: compilador - Mist - 11/09/2023

ata obg

nao esta aki

{
"cmd": ["pawncc.exe", "-i includes", "$file", "-;+"],
"path": "C:/Meus Jogos/samp037_svr_R2-1-1_win32/pawno"
}


RE: compilador - zBreno - 11/09/2023

eu também por muito tempo me perguntava que diabos de mensagem era essa alguns anos depois quando comecei a frequentar o fórum cai nesse tutorial que o Pharrel traduziu da board gringa sobre o uso do 256 https://sampforum.blast.hk/showthread.php?tid=287100

As pessoas tem alguns estranhíssimos costumes sobre strings em pawn a maioria tem a ver com seus tamanhos.
Muitas pessoas pensam que uma string não pode ser maior que 256, o porqué, eu não sei, parece como se fosse imposto um limite que não é necessário e de fato não existe limite algum.
Outras pessoas pensam que todas as strings tem que ser de 256 por nenhuma razão aparente, não importa o quão longa será sua string.
Uma string em pawn é exatamente o mesmo que qualquer outra array, as pessoas não tem nenhum problema com outras arrays, então porque strings?

*Nota-se que a algumas pessoas usam 255 no lugar de 256, mas estes são tão escrotos quanto os outros.

Resumo

Uma string em pawn é apenas uma array de caracteres, sem nenhuma diferença com outras arrays.
Strings são terminadas em NULL, isso quer dizer que todas tem o caracter '\0' (null) no fim (código 0 na tabela ASCII, diferente do caractere '0' o qual é o código 48 da tabela ASCII). Se você tem a seguinte string:

new str[3] = "hi";

Na realidade ele possui 3 células de tamanho - Uma para o 'h', uma para o 'i' e uma para o caractere NULL para sinalizar o fato de que a string terminou. Você também pode escrever assim:

new str[3] = {'h', 'i', '\0'}; ou new str[3] = {104, 105, 0};

104 e 105 são os códigos dos caracteres 'h' e 'i' respectivamente na tabela ASCII e 0 é o código para o caractere NULL.

Em PAWN todas as variáveis são setadas para 0 quando são declaradas, isso quer dizer que quando você faz: new str[256]; na verdade vocк está fazendo:

new str[256];

for (new i = 0; i < 256; i++)
{
str[i] = 0;
}

É mais optimizado que isso mas mesmo assim acaba usando tempo.

Por que não devo usar 256? É lento

Como foi explicado no resumo, todas variáveis são setadas para 0 quando são inicializadas, quanto mais variáveis você tem, mais tempo elas irão ocupar para setar para 0.
Isto é otimizado no assembly, mas não interpretado no PAWN, mas é muito importante considerar que AMXModX escreveu um novo operador, muito similar ao 'new', que declara a variavel mas não
seta a memoria para 0, apenas para contornar este problema.

você não precisa disso

Vou usar um post que eu vi recentemente (ele me motivou a escrever este post):

Originally Posted by X_Cutterz

stock ReturnModeratorCmd(playerid,reqlvl)
{
new rmcmd[256];
format(rmcmd,sizeof(rmcmd),"Only moderators level %d+ can use this command!",reqlvl);
return SendClientMessage(playerid,Green,rmcmd);
}

Vamos assumir que tenha um máximo de 10,000 leveis de admin para ser mais seguro (0 atá 9999), então o número mais longo que vai ser inserido dentro da string tem comprimento de 4 caracteres.

Pelas minhas contas ali tem 47 caracteres na string, 2 deles são o "%d" que não aparece na contagem final da string, então por fim restam 45.

Nós já sabemos que o maior numero será 4 (se você quer ter realmente certeza de proteger o nível de admin, o maior numero possível em PAWN é 11 caracteres (-2147483647)), e nós sabemos que todas as strings requerem o NULL no fim, então o mais longo possível que esta string pode ser é:

47 - 2 + 4 + 1 = 50

50 células, então porque usar 256, é uma perda de 206 células (824 bytes - que chega perto de uma perda de 1 kilobyte de memória)?

O máximo de tamanho de entrada é 128

O chat box do SA:MP tem o tamanho máximo de uma linha de 128 caracteres, se alguém escrever alguma coisa você pode ter certeza que nunca será maior que 128.
Isto inclui textos e comandos, então porque usar um buffer duas vezes maior que o tamanho da saída da string?

[anchor=o128]

O máximo de tamanho da saáda é 128

O chat box do SA:MP tem o tamanho máximo de uma linha de 128 caracteres, se você quer mandar uma mensagem pra alguém é impossível ser maior que 128, então por que usar um buffer maior que isso? Se sua mensagem envolve alguma forma de envio (ex: um comando "/eu") então é altamente recomendável o uso de uma variável de tamanho 128, pois não tem como determinar quão longo será o tamanho da string que ele escreverá, mas você sabe que não pode ser maior que 128.

você não precisa disso 2

public OnPlayerCommandText(playerid, cmdtext[])
{
new string[256], cmd[256];
cmd = strtok(cmdtext, idx);

if (strcmp(cmd, "/num", true) == 0)
{
format(string, sizeof (string), "Random number: %d", random(27));//traduзгo da mensagem "Numero randomico: %d"
SendClientMessage(playerid, 0xFF0000AA, string);
}
}

Ai tem uma pá de coisas erradas com este código, mas infelizmente é um exemplo muito comum de padrão de códigos. Ignorando o fato de estar usando strtok, que é um assunto totalmente diferente, continua sendo um código 'mal feito'.

new string[256], cmd[256];

Por que dois? Por que você precisa de uma string enorme para o comando e outra string enorme para dados que você usara depois sabendo qual comando foi digitado, portanto não precisamos das informações da variável do comando, apenas reutilize a mesma senão você estará dobrando o tempo de processo.

new string[256];

Por que 256? Como foi explicado acima, você sabe de fato que nunca pode ser maior que 128. Se você reutilizar a variável para o envio da mensagem, embora você sabendo que a saída não será maior que 18 caracteres, isto não é totalmente ineficiente tendo em mente que você futuramente ira armazenar todo o tamanho se necessário.

Uma versão mais eficiente poderia ser:

public OnPlayerCommandText(playerid, cmdtext[])
{
new string[128]; // cmdtext NUNCA será maior que 128

string = strtok(cmdtext, idx);

if (strcmp(string, "/num", true) == 0)
{
format(string, sizeof (string), "Random number: %d", random(27)); // Só precisamos de 18 caracteres aqui, mas será necessário 128 futuramente então o tamanho da variável é justificado
SendClientMessage(playerid, 0xFF0000AA, string);
}
}

O uso de Stack

Quando você chama uma função, sua memória esta alocada em uma coisa chamada stack (ou heap, mas eles usam o mesmo espaço em memória para simplificar vamos usar somente a stack), uma função de memória não pode ser estaticamente alocada, pois uma função pode chamar a si mesma, o que requer toda a memória dobrada. Esta área de memória é chamada de memória dinâmica.
Exemplo:

new gVar = 2;

stock StackUse()
{
new str[9];

format(str, sizeof (str), "gVar = %d", gVar);
SendClientMessageToAll(0xFF0000AA, str);
if (gVar)
{
gVar--;
StackUse();
}
}

Esta função será chamada e alocará 9 células na stack para usa-la, então chamara ela mesma e alocara outras 9 células, então chama a si mesma de novo e aloca de novo outras 9 células. Sendo assim ela foi chamada 3 vezes, então são 27 células alocadas na stack. Na terceira vez "gVar" é 0, então a função não chama ela mesma e termina removendo 9 células da stack. Assim passa o controle para a instância anterior da função, que também termina e remove mais 9 células, como feito na primeira instância da função, então agora tem 0 células na stack desta função.

Agora imagine este código

new gVar = 2;

stock StackUse()
{
new str[256];
format(str, sizeof (str), "gVar = %d", gVar);
SendClientMessageToAll(0xFF0000AA, str);
if (gVar)
{
gVar--;
StackUse();
}
}

Exatamente o mesmo que o anterior, mas desta vez sendo chamada 3 vezes a si mesma aloca 768 céulas (3072 bytes, 3 kilobytes) na stack, comparando com as 27 células (108 bytes, 0.1 kilobytes, a redução é maior que 2800%) do original.

Alguns de vocês devem ter visto esta mensagem (ou uma parecida) quando compilam:

Header size: 216 bytes
Code size: 776 bytes
Data size: 528 bytes
Stack/heap size: 16384 bytes; estimated max. usage: unknown, due to recursion
Total requirements: 17904 bytes

ou

Header size: 200 bytes
Code size: 588 bytes
Data size: 512 bytes
Stack/heap size: 16384 bytes; estimated max. usage=10250 cells (41000 bytes)
Total requirements: 17684 bytes

Isto significa que o compilador detectou que você esta usando mais espaço da stack do que esta disponível. Muitas informações importantes são guardadas na stack, como quem chamou a função atual, então pawn sabe quem retornar pra quem. Se você usar muita memória, por causa do jeito que a informação é armazenada, você pode sobrescrever a stack, retornando um ponto randômico no código quase certamente crashando. Por fim você terá um dado corrompido que será sobrescrito por outro dado. Quando as pessoas recebem esta mensagem a dica padrгo é usar "#pragma dynamic", que é uma 'tapeada', e não a solução. Eu acho muito estranho que algo do tamanho de YSI não geram este erro mas pequenos scripts de algumas pessoas geram, você não acha também?

O primeiro erro que eu postei quer dizer que você esta tentando usar mais stack do que é disponível, mas por isso tem algumas funções chamando elas mesmas e o compilador não pode dizer exatamente o quanto você precisa. Note que o compilador não pode determinar quantas vezes uma função pode chamar ela mesma, mesmo no exemplo acima, o numero pode mudar em algum lugar do programa, e geralmente não é uma constante de qualquer jeito. O segundo erro é gerado pelo programa sem exatidão.

Isso se aplica a todas as arrays, mas as strings são as maiores culpadas.

Packed Strings

Um aspecto de pawn raramente usado em SA:MP (devido а algumas natives não suporta-la) é a 'Packed Strings'. Strings normais guardam um caractere por célula e uma célula possui o tamanho de 4 bytes (fazendo células de 256 de exatamente o tamanho de 1 kilobyte), packed strings guardam 4 caracteres por células:

Não packed new string[12] = "Hello there"; // 12 células, 48 bytes

Packed new string[12 char] = !"Hello there"; // 3 células, 12 bytes

Ambas as strings estão no manual do pawn, então eu não vou entrar em muitos detalhes, mas se você tem arrays longas de string para armazenar isso ajudaria para ler em packed strings e usá-las para armazenar. Se este método fosse usado no exemplo do ReturnModeratorCmd, combinado com um tamanho decente de string poderia reduzir o consumo da função de 1 kilobyte (1024 bytes) para 50 bytes, esta é uma redução maior que 2000%.

Quando eu posso usar 256?

Tendo dito tudo isto, ainda tem vezes que o uso de grandes arrays podem ser úteis, mas elas devem ser usadas com moderação somente quando necessárias.

SQL

Leituras em SQL podem ser muito longas, eu tenho escrito algumas em que eu precisei de quase 1024 células, porém isto é somente uma exceção do ponto "Você não precisa disto", neste caso você precisa dela.

Lendo arquivos

Este é um exemplo de entrada sem limite. Se você lé uma linha de um arquivo você não tem como saber o quão longa é acessando a memória para caber tudo e diferentemente do texto digitado dentro do SA:MP, este pode ter qualquer tamanho. Neste caso um belo número redondo como 256 pode cobrir quase todas as eventualidades.

Conclusão

"Em caso de duvida - não entendeu algo". São muito poucos os casos em que usa-se strings pesadas, pense sobre o que você faz para determinar o tamanho de qualquer array, baseado nisto, aplique o mesmo processo em strings.