Falha de segmentação (imagem do núcleo gravada) [RESOLVIDO]

1. Falha de segmentação (imagem do núcleo gravada) [RESOLVIDO]

josé fernando s. andarde
amdrade

(usa Ubuntu)

Enviado em 14/07/2013 - 12:35h

Olá, estou com erro de Falha de segmentação,
o programa e para ler de um arquivo uma lista de nomes de arquivos e retorna a lista ordenada, usando o quicksort, quando passo a lista na mão, funciona, mas quando tento passar a partir do arquivo Falha de segmentação (imagem do núcleo gravada). Código abaixo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef char *string;
int _passo = 0;
int _Ind;
int _n;
FILE *fi;
FILE *fo;
void swap(string *a, string *b){
string t;
t = *a; *a = *b; *b = t;
}
int partition(string lista[], int start, int end) {
int pivot = start;
int left = start , right = end;
int i = 0 ;
string pivotVal;
pivotVal = lista[pivot];
while(left < right)
{
while( strcmp(lista[left],pivotVal)<=0 && left <=end ){
left++;
}
while( strcmp(lista[right],pivotVal)>0 && right >= 0){
right--;
}
if(left < right){
swap(&lista[left], &lista[right]);
}
}
swap(&lista[start],&lista[right]);
swap(&lista[right],&pivotVal);
return right;
}

void quick(string lista[], int start, int end) {
int m = 0;
if(start < end) {
m = partition(lista,start,end);
quick(lista,start,m-1);
quick(lista,m+1,end);
}
}

void display(string lista[],int nmem){
int i =0 ;
for(i = 0; i < nmem;i++)
printf("%s ",lista[i]);
printf("\n");
}

int main(int argc, char *argv[]){
int i = 0;
fi = fopen(argv[1],"r");
fo = fopen(argv[2],"w");
fscanf(fi,"%i",&_n);
string arquivo[_n];
for (i = 1; i < 3; i++) {
fscanf(fi,"%s",arquivo[i]);
}
printf("n=%d\n",_n );
display(arquivo,_n);
quick(arquivo, 0, _n-1);
display(arquivo,_n);

return 0;
}

Arquivo de entrada:

5
bbb.wma
c.wav
aaa.mp3
z.mp3
aaa_b.wav




  


2. Re: Falha de segmentação (imagem do núcleo gravada) [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 15/07/2013 - 06:21h

[/i]O problema é que o que você chamou de string nada mais é do que um ponteiro para caracteres. Um ponteiro é tão-somente uma variável que armazena um endereço de memória.

Dentro de main(), quando você declara arquivo como sendo um array de _n elementos do tipo que você chamou de string, você reservou espaço para _n ponteiros, mas não reservou espaço para os dados propriamente ditos, que são as strings para os quais tais ponteiros deveriam apontar.

Se funcionou para você quando você rodou na mão, você deu azar de ter funcionado, pois deveria ter dado o mesmo tipo de erro.

Mas não se deixe abater por essa confusão. Acho que quase todos nós -- eu, com certeza --, ao começar com C, e especialmente depois de passar por outras linguagens que possuem um tipo de dados especialmente definido para trabalhar com strings, ficamos um pouco confusos por causa do modo que parece (mas não é!) intercambiável de usar arrays e ponteiros.

Quando você declara um array arr com n elementos do tipo T (i.e.: uma declaração na forma T arr[n];), você reserva espaço em memória para cada um dos n elementos. Cada elemento arr[i] (desde que 0<=i<n) se comporta uma variável independente do tipo T independente das que estão armazenadas nos demais elementos.

Em particular, e como a qualquer variável comum, o operador unário & pode ser aplicado a cada elemento arr[i] do array, para retornar o endereço da memória em que esse elemento reside. Por convenção, quando o nome do array aparece numa expressão sem estar com a qualificação de acesso a um elemento específico, isso é sinônimo de obter o endereço do primeiro elemento do array (i.e.: no nosso caso, arr é sinônimo de &arr[0]).

Baseado na minha experiência pessoal quando era iniciante em C, acho que essa notação é uma das princiapais causas de confusão entre arrays e ponteiros, principalmente no caso de arays/ponteiros de caracteres empregados para manipular strings.

(continua)


3. Re: Falha de segmentação (imagem do núcleo gravada) [RESOLVIDO]

josé fernando s. andarde
amdrade

(usa Ubuntu)

Enviado em 15/07/2013 - 23:03h

Olá Paulo, obrigado pela dica, esses ponteiros sempre me confundem, mesmo, mas como devo fazer para alocar o espaço de memória e apontar o retorno da leitura do arquivo para ele ??
Tentei assim mas fica tudo null.

string* arquivo;
arquivo = (string*) malloc(_n * sizeof(string));
printf("n=%d\n",_n );
for (i = 0; i < _n; i++) {
fscanf(fi,"%s",arquivo[i]);
printf("%s \n", arquivo[i]);
}


4. Re: Falha de segmentação (imagem do núcleo gravada) [RESOLVIDO]

josé fernando s. andarde
amdrade

(usa Ubuntu)

Enviado em 16/07/2013 - 00:12h

paulo1205 escreveu:

[/i]O problema é que o que você chamou de string nada mais é do que um ponteiro para caracteres. Um ponteiro é tão-somente uma variável que armazena um endereço de memória.

Dentro de main(), quando você declara arquivo como sendo um array de _n elementos do tipo que você chamou de string, você reservou espaço para _n ponteiros, mas não reservou espaço para os dados propriamente ditos, que são as strings para os quais tais ponteiros deveriam apontar.

Se funcionou para você quando você rodou na mão, você deu azar de ter funcionado, pois deveria ter dado o mesmo tipo de erro.

Mas não se deixe abater por essa confusão. Acho que quase todos nós -- eu, com certeza --, ao começar com C, e especialmente depois de passar por outras linguagens que possuem um tipo de dados especialmente definido para trabalhar com strings, ficamos um pouco confusos por causa do modo que parece (mas não é!) intercambiável de usar arrays e ponteiros.

Quando você declara um array arr com n elementos do tipo T (i.e.: uma declaração na forma T arr[n];), você reserva espaço em memória para cada um dos n elementos. Cada elemento arr[i] (desde que 0<=i<n) se comporta uma variável independente do tipo T independente das que estão armazenadas nos demais elementos.

Em particular, e como a qualquer variável comum, o operador unário & pode ser aplicado a cada elemento arr[i] do array, para retornar o endereço da memória em que esse elemento reside. Por convenção, quando o nome do array aparece numa expressão sem estar com a qualificação de acesso a um elemento específico, isso é sinônimo de obter o endereço do primeiro elemento do array (i.e.: no nosso caso, arr é sinônimo de &arr[0]).

Baseado na minha experiência pessoal quando era iniciante em C, acho que essa notação é uma das princiapais causas de confusão entre arrays e ponteiros, principalmente no caso de arays/ponteiros de caracteres empregados para manipular strings.

(continua)


Olá, Paulo
estou fazendo a alocação dessa forma:

int main(int argc, char *argv[]){
int i = 0;
fi = fopen(argv[1],"r");
fo = fopen(argv[2],"w");
fscanf(fi,"%i",&_n);
char *prt;
prt = (char*)malloc(sizeof(char)*_n);
printf("_n = %d %d\n",_n, (sizeof(char)*_n));
for (i = 0; i < _n; i++) {
fscanf(fi,"%s",&prt[i]);
printf("%s\n", &prt[i]);
}
display(prt,_n);
quick(prt, 0, _n-1);
display(prt,_n);
return 0;
}

porém, a saída vem assim:
_n = 5 5
bbb.wma
c.wav
aaa.mp3
z.mp3
aaa_b.wav

zaaa_b.wav
bcazaaa_b.wav cazaaa_b.wav azaaa_b.wav zaaa_b.wav aaa_b.wav
baazcaa_b.wav aazcaa_b.wav azcaa_b.wav zcaa_b.wav caa_b.wav

:(






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts