Jump to content
whoami-r

Erro ("Segmentation Fault") em função getenv()

Recommended Posts

whoami-r

Boas pessoal, estou a criar uma aplicação servidor-cliente para um trabalho e numa das metas é pedido para utilizar a função getenv().

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

#include "medit-defaults.h"

void dados()
{
	int linhas, colunas, time_out, max_users;
	
	linhas=atoi(getenv("MEDIT_MAXLINES"));
	colunas=atoi(getenv("MEDIT_MAXCOLUMNS"));
	time_out=atoi(getenv("MEDIT_TIMEOUT"));
	max_users=atoi(getenv("MEDIT_MAXUSERS"));
	
	printf("Linhas: %d\tColunas: %d\t Time_Out:%d\t Max_Users:%d\n",linhas,colunas,time_out,max_users);
}

void comandos(char *comando)
{
	int i;
	char *p[2];
	
	*p=strtok(comando," ");

	if(strcmp(*p,"settings")==0)
	{
		dados();
	}

	if(strcmp(*p,"load")==0)
	{
		for(i=1;i<2;i++)
		{
			*(p+i)=strtok(NULL," ");
		}
		printf("Valido.\n");
	}
	
	if(strcmp(*p,"save")==0)
	{
		for(i=1;i<2;i++)
		{
			*(p+i)=strtok(NULL," ");
		}
		printf("Valido.\n");
	}

	if(strcmp(*p,"free")==0)
	{
		for(i=1;i<2;i++)
		{
			*(p+i)=strtok(NULL," ");
		}
		printf("Valido.\n");
	}

	if(strcmp(*p,"statistics")==0)
	{
		printf("Valido.\n");
	}

	if(strcmp(*p,"users")==0)
	{
		printf("Valido.\n");
	}
	
	if(strcmp(*p,"text")==0)
	{
		printf("Valido.\n");
	}	
}

int main(int argc, char* argv[])
{
	int n_linhas,n_col;
	int linhas,colunas;
	char comando[TAM];
	
	printf("Insira o comando:\n");
	scanf("%[^\n]",comando);

	if(strcmp(comando,"shutdown")==0)
	{
		printf("Servidor vai encerrar...\n");
		exit(0);
	}
	else
	{
		comandos(comando);
	}

	return 0;
}

O programa está a funcionar corretamente e de acordo com aquilo que é necessário por agora, mas quando introduzo o comando "settings" aparece-me o erro 'Segmentation fault' e termina
Já rodei o programa no windows e não me acontece este erro, gostaria de saber pq é que no linux isto acontece.

Para o caso de ajudar melhor a entender o meu problema, deixo também o header file 

#ifndef MEDITDEFAULTS_H
#define MEDITDEFAULTS_H

#ifdef __cplusplus
extern "C" {
#endif

#define TAM 50
#define TAM_USER 8
#define MEDIT_MAXCOLUMNS 45


//STRUCT PARA AS CARACTERISTICAS DO UTILIZADOR
typedef struct Utilizador
{
	char nome[TAM_USER];
	int client_pid;
}User;


//STRUCT PARA ACOLHER O TEXTO EM EDICAO
typedef struct texto_edicao
{
	char linha[MEDIT_MAXCOLUMNS];
	char username[TAM_USER];
	int client_pid;
}Edicao;


#ifdef __cplusplus
}
#endif

#endif /* MEDIT_DEFAULTS_H*/

Obrigado

Edited by riqu3s

Share this post


Link to post
Share on other sites
Rui Carlos

Não estás a validar o valor devolvido pelo getenv, pelo que corres o risco de chamar a função atoi com NULL, o que resulta num segmentation fault.

Começa por colocar o resultado do getenv numa variável, e testa se o mesmo é diferente de NULL antes de chamares o atoi.

Share this post


Link to post
Share on other sites
whoami-r
23 minutos atrás, Rui Carlos disse:

Não estás a validar o valor devolvido pelo getenv, pelo que corres o risco de chamar a função atoi com NULL, o que resulta num segmentation fault.

Começa por colocar o resultado do getenv numa variável, e testa se o mesmo é diferente de NULL antes de chamares o atoi.

void mostra_dados()
{
	int linhas, colunas, time_out, max_users;
	
	char *maxlines = getenv("MEDIT_MAXLINES");
	char *maxcolumns = getenv("MEDIT_MAXCOLUMNS");
	char *timeout = getenv("MEDIT_TIMEOUT");
	char *maxusers = getenv("MEDIT_MAXUSERS");
	
	if(maxlines == NULL || maxcolumns == NULL || timeout == NULL || maxusers == NULL)
	{
		printf("Erro de segmentação\n");
		exit(0);
	}
	else
	{
		linhas=atoi(maxlines);
		colunas=atoi(maxcolumns);
		time_out=atoi(timeout);
		max_users=atoi(maxusers);
	}
	
	printf("Linhas: %d\tColunas: %d\t Time_Out:%d\t Max_Users:%d\n",linhas,colunas,time_out,max_users);
}

Tentei fazer o que disse, mas o que acontece é que me é apresentada a mensagem do printf("Erro de Segmentação")

Significa que os getenv() estão a dar NULL, ou pelo menos um deles. Como é que posso contornar isso?

Edited by riqu3s

Share this post


Link to post
Share on other sites
Rui Carlos
11 minutos atrás, riqu3s disse:

Tentei fazer o que disse, mas o que acontece é que me é apresentada a mensagem do printf("Erro de Segmentação");

E é isso que estás a dizer à aplicação para fazer quando as variáveis de ambiente não estão definidas, não é?

Provavelmente devias mudar a mensagem para algo como "Uma das variáveis de ambiente necessárias para esta operação não está definida.  Tente novamente depois de definir todas as variáveis.", visto que não há ali nenhum erro de segmentação, mas sim um erro na utilização do programa.

 

Aquela modificação apenas torna o programa mais robusto, evitando que o mesmo falhe em caso de utilização incorrecta por parte do utilizador.  Depois é preciso que o utilizador corrija a forma como chama o programa, definindo as variáveis.  Podes mostrar como é que estás a definir as variáveis de ambiente?

Share this post


Link to post
Share on other sites
whoami-r
12 minutos atrás, Rui Carlos disse:

E é isso que estás a dizer à aplicação para fazer quando as variáveis de ambiente não estão definidas, não é?

Provavelmente devias mudar a mensagem para algo como "Uma das variáveis de ambiente necessárias para esta operação não está definida.  Tente novamente depois de definir todas as variáveis.", visto que não há ali nenhum erro de segmentação, mas sim um erro na utilização do programa.

 

Aquela modificação apenas torna o programa mais robusto, evitando que o mesmo falhe em caso de utilização incorrecta por parte do utilizador.  Depois é preciso que o utilizador corrija a forma como chama o programa, definindo as variáveis.  Podes mostrar como é que estás a definir as variáveis de ambiente?

Como é que defino as variáveis de ambiente?

Share this post


Link to post
Share on other sites
Rui Carlos

Uma de definires a variável é colocando a definição da mesma antes de cada chamada ao programa (e.g. TESTVAR="value" ./prog), que define a variável (TESTVAR) visível pela aplicação chamada no mesmo comando (prog).  Outra é usando o export (e.g. export TESTVAR="value"), que define uma variável visível aos programas chamados futuramente da mesma shell.

Share this post


Link to post
Share on other sites
whoami-r
6 minutos atrás, Rui Carlos disse:

Uma de definires a variável é colocando a definição da mesma antes de cada chamada ao programa (e.g. TESTVAR="value" ./prog), que define a variável (TESTVAR) visível pela aplicação chamada no mesmo comando (prog).  Outra é usando o export (e.g. export TESTVAR="value"), que define uma variável visível aos programas chamados futuramente da mesma shell.

E não há nenhuma forma de definir uma variável no código do programa, de forma a que sempre que o programa é chamado, essas variáveis passam a estar definidas?

Share this post


Link to post
Share on other sites
Rui Carlos
4 minutos atrás, riqu3s disse:

E não há nenhuma forma de definir uma variável no código do programa, de forma a que sempre que o programa é chamado, essas variáveis passam a estar definidas?

Haver há, mas não faz sentido nenhum.  Isso seria o mesmo que ter variáveis globais (com complicações adicionais), que são altamente desaconselhadas.

Aquilo que deves fazer é passar as variáveis às funções como parâmetros.

Share this post


Link to post
Share on other sites
whoami-r
2 minutos atrás, Rui Carlos disse:

Haver há, mas não faz sentido nenhum.  Isso seria o mesmo que ter variáveis globais (com complicações adicionais), que são altamente desaconselhadas.

Aquilo que deves fazer é passar as variáveis às funções como parâmetros.

Hmm ok, acho que já percebi. Obrigado pela atenção e explicação

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.