Rechercher : dans
Par :

[ C ] segmentation fault avant le main()

Dernière réponse le 30 jan 2009 à 12:00:43 FlyerBut, le 28 jan 2009 à 16:53:41 
 Signaler ce message aux modérateurs

Bonjour,


j'ai un petit programme en C, quand je l'exécute sur mon ordinateur, pas de problème

Puis j'envoie le fichier .c et l'exécutable sur un serveur, je met un chmod de 777 pour être certain

Mais il m'envoie un segmentation fault dès que je veux l'exécuter ( commande: ./programmeTest )

Pourtant j'ai mit des printf juste en entrant dans le main, il affiche rien donc je suppose qu'il rentre même pas dans mon programme...


Quelqu'un a-t-il une idée du pourquoi ça plante sur le serveur et pas sur mon pc local?


je vois pas du tout :s


Merci de votre aide

Configuration: Windows XP
Firefox 3.0.3

1

kilian, le 28 jan 2009 à 16:57:28

Met bien des "\n" à la fin de tes chaines pour printf, afin de bien vider le buffer dès l'appel à printf.
Sinon à part ça, sans le code source on ne peut pas t'aider. Ce message ne mange ni trop gras, ni trop salé, ni trop
sucré .Pour sa santé il bouge plus et mange 5 fruits et 
légumes par jour.

Répondre à kilian

13

Char Snipeur, le 30 jan 2009 à 10:25:27

Les \n ne vident pas le buffer. faire un fflush(stdout); pour ça. ou endl en C++. Salutation !
Char Snipeur

Répondre à Char Snipeur

14

kilian, le 30 jan 2009 à 10:36:02

T'es sûr?
Il me sembl qu'il ya pas besoin de passer par le fflush explicite. Ce message ne mange ni trop gras, ni trop salé, ni trop
sucré .Pour sa santé il bouge plus et mange 5 fruits et 
légumes par jour.

Répondre à kilian

16

Char Snipeur, le 30 jan 2009 à 10:43:08

Quasiment. Mes programmes de calcul qui sortent beaucoup de résultats dans des fichiers ou en sortie standard écrivait par bloc indépendamment des retours à la ligne. Et je vois mal printf aller voir si le dernier caractère est un \n (qui selon les OS peut être \r ou \n\r) pour vider le buffer. Mais bon... ma mémoire me joue peut être des tours, il faudrait aller voir les spécifications de printf. Salutation !
Char Snipeur

Répondre à Char Snipeur

17

kilian, le 30 jan 2009 à 11:21:08

Et je vois mal printf aller voir si le dernier caractère est un \n (qui selon les OS peut être \r ou \n\r) pour vider le buffer.

Il me semble que c'est pas un truc propre à printf mais plutôt aux flots de caractères dans les terminaux.
Attends, je vais essayer de retrouver les lignes correspondantes dans les drivers tty de Linux, il me semble être tombé là-dessus l'autre jour... Ce message ne mange ni trop gras, ni trop salé, ni trop
sucré .Pour sa santé il bouge plus et mange 5 fruits et 
légumes par jour.

Répondre à kilian

2

dubcek, le 28 jan 2009 à 17:02:39

Hello
les 2 ordinateurs tournent le même système d'exploitation ?

Répondre à dubcek

3

FlyerBut, le 29 jan 2009 à 15:22:24

Voici mon code:

const char *progname = "test_snmp";
const char *revision = "$Revision: 1.0 $";
const char *copyright = "2009-01-23";
const char *email = "exemple@gmail.com";

#include "common.h"
#include "utils.h"
#include "popen.h"
#include <dbi/dbi.h>


#define DEFAULT_COMMUNITY "public"
#define DEFAULT_OID "1.3.6.1.4.1.9.9.156.1.2.1.1.5."
#define DEFAULT_PORT "161"
#define DEFAULT_PROTOCOL "1"
#define DEFAULT_TIMEOUT "3"
#define DEFAULT_RETRIES "0"

#define DEFAULT_DELIMITER "="
#define DEFAULT_OUTPUT_DELIMITER " "

#define MAX_DELIM_LENGTH 8

int process_arguments (int, char **);
void print_usage (void);


char *server_address = NULL;
char *server_port;
char *community = NULL;
char *network_interface = "1";
char *destination = "0";

char *oid;
char *retries;

char *delimiter;
char *output_delim;
char perfstr[MAX_INPUT_BUFFER] = "";


int main (int argc, char **argv)
{
	int i = 0;
	int result = STATE_UNKNOWN;
	int found = 0;
	
	char input_buffer[MAX_INPUT_BUFFER];
	char *command_line = NULL;
	char *response = NULL;
	char *outbuff;
	char *output;
	char *ptr = NULL;
	char *p2 = NULL;
	char *show = NULL;
	char type[8] = "";
	unsigned int istate;
	
	setlocale (LC_ALL, "");
	bindtextdomain (PACKAGE, LOCALEDIR);
	textdomain (PACKAGE);

	/* Configure  variables */
	outbuff = strdup ("");
	output = strdup ("");
	delimiter = strdup (" = ");
	output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
	
	server_port = strdup (DEFAULT_PORT);
	retries = strdup (DEFAULT_RETRIES);
	oid = strdup (DEFAULT_OID);
	
	
	/* Parse parametres  */
	if (process_arguments (argc, argv) == ERROR)
		usage4 (_("Could not parse arguments"));

		
	/* Genere OID */
	strcat(oid, network_interface);		
		
		
	printf("\n%s -t %s -r %s -v 1 -c %s %s %s",PATH_TO_SNMPGET, DEFAULT_TIMEOUT, retries, community, server_address, /*server_port,*/ oid);
	/* Genere commande */
	asprintf (&command_line, "%s -t %s -r %s -v 1 -c %s %s %s",
			PATH_TO_SNMPGET, DEFAULT_TIMEOUT, retries, community, server_address, /*server_port,*/ oid);

	/* run the command */
	child_process = spopen (command_line);
	if (child_process == NULL) {
		printf (_("Could not open pipe: %s\n"), command_line);
		exit (STATE_UNKNOWN);
	}

	// Lecture resultat
	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
		asprintf (&output, "%s%s", output, input_buffer);

	ptr = output;
	

	while (ptr) 
	{
		char *foo, *ptr2;
		unsigned int copylen;

		foo = strstr (ptr, delimiter);
		copylen = foo-ptr;
		if (copylen > sizeof(perfstr)-strlen(perfstr)-1)
			copylen = sizeof(perfstr)-strlen(perfstr)-1;
		ptr2 = ptr;
		ptr = foo; 

		if (ptr == NULL)
			break;

		ptr += strlen (delimiter);
		ptr += strspn (ptr, " ");

		found++;

		if (ptr[0] == '"') 
		{
			ptr++;
			response = strpcpy (response, ptr, "\"");
			ptr = strpbrk (ptr, "\"");
			ptr += strspn (ptr, "\"\n");
		}
		else {
			response = strpcpy (response, ptr, "\n");
			ptr = strpbrk (ptr, "\n");
			ptr += strspn (ptr, "\n");
			while (strstr (ptr, delimiter) && strstr (ptr, "\n") && strstr (ptr, "\n") < strstr (ptr, delimiter)) 
			{
				response = strpcat (response, ptr, "\n");
				ptr = strpbrk (ptr, "\n");
			}
			if (ptr && strstr (ptr, delimiter) == NULL) 
			{
				asprintf (&response, "%s%s", response, ptr);
				ptr = NULL;
			}
		}

		/* We strip out the datatype indicator for PHBs */

		/* Clean up type array - Sol10 does not necessarily zero it out */
		bzero(type, sizeof(type));

		if (strstr (response, "Gauge: "))
			show = strstr (response, "Gauge: ") + 7;
		else if (strstr (response, "Gauge32: "))
			show = strstr (response, "Gauge32: ") + 9;
		else if (strstr (response, "Counter32: ")) 
		{
			show = strstr (response, "Counter32: ") + 11;
			strcpy(type, "c");
		}
		else if (strstr (response, "Counter64: ")) 
		{
			show = strstr (response, "Counter64: ") + 11;
			strcpy(type, "c");
		}
		else if (strstr (response, "INTEGER: "))
			show = strstr (response, "INTEGER: ") + 9;
		else if (strstr (response, "STRING: "))
			show = strstr (response, "STRING: ") + 8;
		else
			show = response;
		p2 = show;

		
		
		/* Analyse resultat et update db */
		printf("\nName: %s", p2);
		/* fin analyse */
			
	}	/* end while (ptr) */

	if (found == 0)
	{
		
		die (STATE_UNKNOWN, "No data received from host\n");
	}

	/* close the pipe */
	if (spclose (child_process)) 
	{
		if (result == STATE_OK)
			result = STATE_UNKNOWN;
			
		asprintf (&outbuff, "%s (%s)", outbuff, "snmpget returned an error status");
	}

	printf ("%s\n", outbuff);

	return result;
}



/* process command-line arguments */
int process_arguments (int argc, char **argv)
{
	char *ptr;
	int c = 1;
	int j = 0, jj = 0, ii = 0;

	int option = 0;
	static struct option longopts[] = {
		STD_LONG_OPTS,
		{"community", required_argument, 0, 'C'},
		{"interface", required_argument, 0, 'I'},
		{"destination", required_argument, 0, 'D'},
		{0, 0, 0, 0}
	};

	if (argc < 2)
		return ERROR;

	while (1) 
	{
		c = getopt_long (argc, argv, "C:H:P:R:I:D:", longopts, &option);

		if (c == -1 || c == EOF)
			break;

		switch (c) 
		{
			case 'C':									/* group or community */
				community = optarg;
				break;
			case 'H':									/* Host or server */
				server_address = optarg;
				break;
			case 'P':									/* Port */
				server_port = optarg;
				break;				
			case 'R':									/* Retry */
				retries = optarg;
				break;	
				
			case 'I':	/* interface */
				network_interface = optarg;
				break;
			case 'D':	/* destination */
				destination = optarg;
				break;	
		}			
	}
	
	return OK;
}



void print_usage (void)
{
  printf (_("Usage:"));
  printf ("%s -H <ip_address>\n", progname);
  printf ("-C <community>\n");
  printf ("-I <interface>\n");
  printf ("-D <destination>\n");
  
  printf ("[-P <server_port>]\n");
  printf ("[-R <retry count>]\n");
}




les 2 OS sont Ubuntu...

Je ne comprends tjs pas...

en ligne de commande via : snmpget -t 3 -r 0 -v 1 -c nomCommunaute ip 1.3.6.1.4.1.9.9.156.1.2.1.1.5.1
ça fonctionne dans les 2 OS!!!

Je ne comprends tjs pas pq le programme me lance un segmentation fault avant de rentrer dans le main...

Si quelqu'un a une idée?

Répondre à FlyerBut

4

dubcek, le 29 jan 2009 à 15:29:19
  • +1

Démarre le avec
strace ton_prog
pour avoir une idée de ce qu'il fait avant de crasher

Répondre à dubcek

5

kilian, le 29 jan 2009 à 15:57:32

Très juste!
Quoique je suggèrerais peut être d'essayer ltrace plutôt que strace.

ltrace te fournira l'appel aux fonction de bibliothèques externes (fopen/strdup etc...) tandis que strace ne t'indiquera
que les appels systèmes (open/read....), ce qui est généralement plus difficile à situer dans le code....

ltrace ./monprogramme Ce message ne mange ni trop gras, ni trop salé, ni trop
sucré .Pour sa santé il bouge plus et mange 5 fruits et 
légumes par jour.

Répondre à kilian

6

FlyerBut, le 29 jan 2009 à 16:26:30

L'exécution de strace donne:

execve("./test_snmp",["./test_snmp"],/*18vars*/)=0
brk(0) =0x804f000
--- SIGSEGV (segmentation fault) @0 (0) ---
+++ killed by SIGSEGV +++
Process 7529 detached


l'exécution de ltrace donne:

ltrace: Couldn't get section header from "./test_snmp"



:s :s

Comment faire disparaitre le segmantation fault avec ces infos?

Répondre à FlyerBut

7

dubcek, le 29 jan 2009 à 16:30:22

Que dit
file test_snmp
et sur les 2 systèmes
echo $LD_LIBRARY_PATH

Répondre à dubcek

8

FlyerBut, le 29 jan 2009 à 16:51:04

La commande file renvoie sur l'OS où le prgr tourne:

test_snmp: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.8, dynamically linked (uses shared libs), not stripped

la commande file renvoie sur l'OS où le prgr tourne pas:

test_snmp: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.8, dynamically linked (uses shared libs), stripped


le echo $LD_LIBRARY_PATH me renvoie une ligne "blanche" sur les 2 OS

Répondre à FlyerBut

9

kilian, le 29 jan 2009 à 17:13:10

Pourrais-tu donner le résultat de cette commandes sur les deux?

ldd /bin/ls

Comme ça on verra la version des bibliothèques qu'ils utilisent, particulièrement la glibc. Si ces versions sont différentes, alors ça peut coincer. Ce message ne mange ni trop gras, ni trop salé, ni trop
sucré .Pour sa santé il bouge plus et mange 5 fruits et 
légumes par jour.

Répondre à kilian

10

dubcek, le 29 jan 2009 à 17:13:43

Est-ce que compiler un petit prog. sur le 2ème système fonctionne ?

main(){printf("hello world\n");}
gcc -o prog prog.c
./prog

Répondre à dubcek

11

FlyerBut, le 29 jan 2009 à 17:41:13

Sur celui qui fonctionne ldd /bin/ls:

linux-gate.so.1 => (0xb7f80000)
librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb7f6f000)
libselinux.so.1 => /lib/libselinux.so.1 (0xb7f56000)
libacl.so.1 => /lib/libacl.so.1 (0xb7f4e000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7dff000)
libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7de7000)
/lib/ld-linux.so.2 (0xb7f81000)
libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7de3000)
libattr.so.1 => /lib/libattr.so.1 (0xb7ddf000)


sur celui du segmentation fault:

linux-gate.so.1 => (0xb7f80000)
librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb7f6f000)
libselinux.so.1 => /lib/libselinux.so.1 (...)
libacl.so.1 => /lib/libacl.so.1 (...)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (...)
libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (...)
/lib/ld-linux.so.2 (...)
libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (...)
libattr.so.1 => /lib/libattr.so.1 (...)

il y a les numeros entre ( ) qui changent...



Pour compiler, ça fonctionne correctement



J'ai fais d'autre tests, des recherches dans googles .. mais rien, tjs ce segmentation fault!
:s


quelqu'un a peut-être une idée avec toutes ces infos?

Répondre à FlyerBut

12

dubcek, le 30 jan 2009 à 09:45:28

Essaye de recompiler et linker ton programme en static :
gcc -static -static-libgcc ...
pour voir si c'est un problème avec les librairies, en static les modules font faire patrie de l'exécutable alors qu'en dynamique/shared il va utiliser celles du système hôte

Répondre à dubcek

15

Char Snipeur, le 30 jan 2009 à 10:38:11

Salut.
Je n'ai pas la solutions, mais quelques pistes.
J'ai déjà eu ce problème en utilisant QT, une recompilation complète de mon programme réglai le problème en général. Parfois cela venais d'une mauvaise initialisation de variable. Car il faut bien voir que des choses se font avant le main : initialisation de variable de classes (ou struct) etc.
Une autre erreur se produit sur mon Linux, si je fait un petit programma en utilisant pthread, celui-ci compil très bien avec ou sans le lien -lpthread.
Mais sans une erreur de segmentation avant le main se produit, alors qu'avec pas de souci.

Je te conseil donc de faire des tests de simplification jusqu'à ce que ça fonctionne. Dans l'ordre :
vide les main
supprime les include un à un jusqu'à ce que ça fonctionne
supprime les variables static.

à part :

	int option = 0;
	static struct option longopts[] = {

Je ne comprends pas cette déclaration, que vient faire un entier là dedans ? (on en apprend tout les jours en C !) Salutation !
Char Snipeur

Répondre à Char Snipeur

18

loupius, le 30 jan 2009 à 11:50:45

Comme toi, je suis resté quelque peu perplexe face à cette ligne. Alors j'ai essayé le programme suivant:

#include<stdio.h>

struct option
{
  int x;
  int y;
};

int main(void)
{
  int i;
  int option = 123;
  static struct option tOption[] = { {1, 11}, {2, 22} };

  printf ("option=%d\n", option);
  for (i=0; i< 2; i++)
    printf("i=%d x=%d y=%d\n", i, tOption[i].x, tOption[i].y);

  return (0);
}
Et ça marche !!! Le compilateur ne confond pas 'int option' et 'struct option'.
A la réflexion, c'est logique... mais, à mon humble avis, ce n'est vraiment pas une bonne pratique.

Répondre à loupius

19

 Char Snipeur, le 30 jan 2009 à 12:00:43

OK, en fait, il doit considérer le premier mot venant derrière le mot "struct" comme un identificateur, sans tenter de l'interpréter avec ce qui a été fait avant. D'ailleurs, nous n'avons pas la définition de la structure "option" avant.
Ce n'est pas une bonne pratique pour la lisibilité. Salutation !
Char Snipeur

Répondre à Char Snipeur