2009-07-11 11 views
2

Je suis en train de faire un peu de développement C classique dans Visual C++ 2008 qui modifiera les caractères d'une chaîne comme ceci:exception non gérée lorsque déréférencement pointeur caractère dans Visual C++ 2008

void ModifyString(char *input) 
{ 
    // Change first character to 'a' 
    *input = 'a'; 
} 

Je reçois exception non gérée lorsque j'essaie de changer un personnage. Il semble que je pourrais le faire dans Visual Studio 6 ou en utilisant gcc, mais peut-être que j'oublie quelque chose. Est-ce que Visual Studio transmet en quelque sorte char * par valeur (gestion de la mémoire). Si oui, comment puis-je l'éteindre?

+1

peut en savoir plus sur la façon dont vous appelez cette fonction ... pourriez-vous donner plus d'exemple? –

+0

S'il est NULL. Ce qui se produit? –

Répondre

8

vous passez probablement une chaîne littérale quelque part:

ModifyString("oops"); // ERROR! 

C et C++ vous permettent d'implici tly cast de littéraux de chaîne (qui ont le type const char[]) à char*, mais une telle utilisation est obsolète. Les constantes de chaîne sont autorisées à être allouées en mémoire morte (et elles le sont généralement), donc si vous tentez de les modifier, vous obtiendrez une violation d'accès (erreur de segmentation ou erreur de bus). Si le compilateur ne place pas les constantes de chaîne dans la mémoire morte, le programme fonctionnera toujours, mais il s'agit d'un comportement indéfini.

La bonne façon de le faire est de copier la chaîne dans un tampon inscriptible:

// one way: 
char mystring[] = "test"; 
ModifyString(mystring); // ok 

// another way: 
char mystring[64]; // make sure this is big enough!! 
strcpy(mystring, "test"); 
ModifyString(mystring); // ok 
+0

Oui, c'était ça. Mon pilote déclarait les chaînes de test comme suit: char * test = "Hello World!" Je l'ai changé pour utiliser des tableaux char comme vous l'avez décrit et cela a fonctionné. Merci pour les réponses rapides. –

+0

@Brian: Assurez-vous de ne pas écrire après la fin de votre tampon dans ModifyString ou vous aurez beaucoup plus gros problème. – Paul

1

L'entrée est-elle une chaîne littérale? C'est probablement le problème. Sinon, vous devrez poster plus de code, car le pointeur a fini par pointer vers un emplacement en lecture seule en mémoire.

1

Il est impossible de répondre à cette question sans voir comment ModifyString est appelée. La fonction elle-même est correcte en supposant que son contrat doit recevoir une valeur non NULL.

Cependant, il est possible pour le site d'appel à l'échec en faisant un certain nombre de choses

  • Passing NULL
  • Passing const char au moyen d'un mal jeté
+0

vous n'avez pas besoin d'avoir un "casting diabolique" pour passer accidentellement un const char * à la fonction. en C les littéraux de chaîne sont tapés "char *" même s'ils sont constants – newacct

+1

@newacct - c'est mal! –

+0

@newacct: Non, les littéraux de chaîne C sont de type 'const char []'. Il arrive juste qu'il y ait une conversion implicite des littéraux de chaîne en 'char *'. La raison en était que lorsqu'ils normalisaient le langage C, il y avait beaucoup de code hérité supposant que les constantes de chaîne étaient modifiables, et le comité ANSI ne voulait pas invalider tout ce code existant. Malheureusement, C++ a également hérité de cette distribution implicite, bien qu'elle soit obsolète. –

0

Je ne peux pas dire exactement pourquoi cela ne fonctionne pas, mais le problème est dans votre code, pas Visual Studio. Pour une raison quelconque, vous passez un pointeur invalide à la fonction. Il s'agit soit d'un pointeur nul, soit d'une adresse vers laquelle vous n'avez pas accès en lecture.

Si vous publiez un peu plus du code (où est appelée la fonction, et comment s'appelle-t-elle?), Nous pouvons être en mesure de signaler le problème exact.

La raison pour laquelle cela a fonctionné dans GCC ou VC6 est tout simplement que c'est un comportement indéfini. La norme C++ ne dit pas que "cela devrait fonctionner", ou "cela devrait provoquer un crash". Tout peut arriver si vous écrivez en mémoire à laquelle vous n'avez pas accès. Et en fonction du compilateur et du système sur lequel vous exécutez l'application, l'adresse à laquelle vous accédez finira par varier. Par pure chance, vous frappez une adresse qui a provoqué une violation d'accès lors de la compilation avec VC2008. Sous GCC et VC6, vous n'étiez pas aussi chanceux, et avez obtenu le code qui a semblé fonctionner, et a simplement écrit à une certaine adresse de poubelle.