[ C ] segmentation fault avant le main()

Fermé
FlyerBut - 28 janv. 2009 à 16:53
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 - 30 janv. 2009 à 12:00
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

11 réponses

dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
29 janv. 2009 à 15:29
démarre le avec
strace ton_prog
pour avoir une idée de ce qu'il fait avant de crasher
1
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
29 janv. 2009 à 15:57
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
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
28 janv. 2009 à 16:57
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.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
30 janv. 2009 à 10:25
les \n ne vident pas le buffer. faire un fflush(stdout); pour ça. ou endl en C++.
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527 > Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023
30 janv. 2009 à 10:36
T'es sûr?
Il me sembl qu'il ya pas besoin de passer par le fflush explicite.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297 > kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016
30 janv. 2009 à 10:43
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.
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527 > Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023
30 janv. 2009 à 11:21
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...
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
28 janv. 2009 à 17:02
hello
les 2 ordinateurs tournent le même système d'exploitation ?
0
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?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
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?
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
29 janv. 2009 à 16:30
que dit
file test_snmp
et sur les 2 systèmes
echo $LD_LIBRARY_PATH
0
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
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
29 janv. 2009 à 17:13
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.
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
29 janv. 2009 à 17:13
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
0
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?
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
30 janv. 2009 à 09:45
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
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
30 janv. 2009 à 10:38
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 !)
0
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.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
30 janv. 2009 à 12:00
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é.
0