EP2 - SegFault com executável fornecido e imagem 1

EP2 - SegFault com executável fornecido e imagem 1

por Vinícius Bitencourt Matos -
Número de respostas: 3

Ao abrir com o executável fornecido a imagem 1 na rede Linux:

./ep2-linux imagem1.ppm
Arquivo 'imagem1.ppm' com a imagem foi aberto.
A imagem foi carregada e o arquivo 'imagem1.ppm' foi fechado.

Grupos de pixeis conexos e de mesma cor:
Segmentation fault

As demais imagens abrem sem erro com o mesmo executável, e a imagem 1 é exibida sem erro no GIMP.

Em resposta à Vinícius Bitencourt Matos

Re: EP2 - SegFault com executável fornecido e imagem 1

por José Coelho de Pina -

Ao abrir com o executável fornecido a imagem 1 na rede Linux:

Legal!

O problema é que quando a região é meio grande então o número de chamadas recursivas feita pela função é muito grande e ocorre um erro de segmenção (stack overflow). Na imagem1.ppm a região conexa de cor preta é meio grande. Para rodar o programa sem erro de segmentação para esta imagem faça o seguinte.

No prompt do linux escreva

meu_prompt> ulimit -a

Isto deve mostrar vários limites do seu sistema. No meu caso mostra:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 26052
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192        <<<<<<<<<<<<<<
cpu time               (seconds, -t) unlimited
max user processes              (-u) 26052
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Veja que o meu stack size é 8192 kbytes. Para alterar esse valor você
pode-se escrever

meu_prompt> ulimit -s  16000

Depois disto veja o resultado de ulimit -a

meu_prompt>ulimit -a 
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 26052
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 16000         <<<<<<<<<<<<<<<<<
cpu time               (seconds, -t) unlimited
max user processes              (-u) 26052
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
 

Para alterar o stack size você tambem pode proceder como está descrito no FAQ
e compilar com a opção -Wl,--stack,16384000, aproximadamente 16MB.

Por favor, teste estas opções e escreva aqui sobre o que você descobrir.

Em resposta à José Coelho de Pina

Re: EP2 - SegFault com executável fornecido e imagem 1

por Vinícius Bitencourt Matos -

O valor citado também estava em 8192, e após mudar para 16000 a imagem abriu normalmente.

Para compilar com a opção -Wl(...) no Linux (sem trocar esse valor pelo terminal), é necessário alterar o Makefile? Se sim, esse código deve ser adicionado ao fim da linha que começa com GLLIB?

Em resposta à Vinícius Bitencourt Matos

Re: EP2 - SegFault com executável fornecido e imagem 1

por José Coelho de Pina -

Para compilar com a opção -Wl(...) no Linux (sem trocar esse valor pelo terminal), é necessário alterar o Makefile?

Hmmm.
Depois eu escrevo mais sobre isto, mas no momento da para dizer que tem algum problema com essas opções no linux  tímido (pelo menos com a minha distribuição Ubuntu) .

Gerei o executável para o Windows (no Vista) usando a opção Wl,--stack=10000000
como diz o FAQ da EP2 e tudo funcionou direito, ou seja, o programa explodia quando eu
carregava a imagem imagem1.ppm e depois que coloquei essa opção para aumentar
o stack limit o programa parou de explodir maneiro.

No linux, ao colocar essa opção (bem, tem que modificar um pouco...) aparecia uma mensagem de "opção stack não reconhecida" pensativo. Andei olhando por ai e parece que isto é realmente um problema, mas preciso investicar mais (isto fica para uma próxima mensagem).

Bem, o que eu queria mesmo escrever é que na página

http://stackoverflow.com/questions/2275550/change-stack-size-for-a-c-application-in-linux-during-compilation-with-gnu-com

há uma descrição de como, no início do programa (main()), colocar um trecho de código
que aumenta o stack limit.  Achei o código bacana boca aberta. Para isto, no EP2, é necessário colocar

#include <sys/resource.h>

junto com os includes e o ínicio do main() fica assim

int 
main(int argc, char *argv[])
{
  ImagemRGB *imgOriginal  = NULL; /* ponteiro para a imagem original */
  ImagemRGB *tela         = NULL; /* ponteiro para a imagem corrente ou atual */
  CelRegiao *listaRegioes = NULL; /* ponteiro para a lista de regioes */
  
  /* trecho copiado de 
  http://stackoverflow.com/questions/2275550/change-stack-size-for-a-c-application-in-linux-during-compilation-with-gnu-com
  */
  const rlim_t kStackSize = 16 * 1024 * 1024;   /* min stack size = 16 MB */
  struct rlimit rl;
  int result;

  result = getrlimit(RLIMIT_STACK, &rl);
  if (result == 0)
    {
      if (rl.rlim_cur < kStackSize)
        {
	  rl.rlim_cur = kStackSize;
	  result = setrlimit(RLIMIT_STACK, &rl);
	  if (result != 0)
            {
	      fprintf(stderr, "setrlimit returned result = %d\n", result);
            }
        }
    }

Testei e funcionou como especificado mostrando a língua.

Bem, o -Wl,--stack... fica para uma outra mensagem.