2010-07-11 10 views
0

Extrait de code à suivre.public char * membre d'une classe/struct inaccessible?!?!? Po

J'ai une structure (exemple de code a classe, essayé les deux, même effet) qui va stocker un certain nombre de char *. J'ai fait un constructeur pour la classe qui initialise la plupart d'entre eux à = ""; Lors de la tentative de modification de ce membre d'une instance de la classe, strncpy et all reportent l'accès refusé. Ces fonctions rapportent même un accès refusé quand je les utilise dans le cadre des fonctions internes de structure/membre de la classe. Cela a été mon hypothèse que d'avoir un membre char * d'une structure/classe n'était pas un gros problème et rien de spécial (en plus d'être un pointeur vers un char, ce qui nécessite qu'il soit initialisé avant d'être utilisé, et détruit à certains moments). J'apprécie que quelqu'un puisse me dire où mes hypothèses ont été fausses, et me diriger vers une littérature qui permettrait de clarifier ce qui se passe. Je suis en train de compiler le code sous la version complète de vs2008.

Je m'attends à ce que quelqu'un qui exécutera ce code reçoive une erreur d'exécution au sujet d'un accès refusé à un certain emplacement de mémoire.

Je m'attends aussi à ce que quand je fais un char * mystr que quand je dis plus tard mystr = ""; que la mémoire est initialisée pour mystr pour ensuite être utilisée. Je voudrais aussi penser que je ne suis pas un idiot, mais quand j'essaie d'utiliser la fenêtre locale pour déterminer l'adresse mémoire précise d'une certaine variable, je n'arrive pas à comprendre moi où la mémoire est à. Je dois avoir de la chance dans la fenêtre de la mémoire. tant pis.

aide! Merci d'avance. Je déteste faire face à ces charmes stupides, je les gâche toujours quelque part, et mes hypothèses sur la façon dont ils fonctionnent sont fausses. Je veux changer cela pour que je les commande comme les outils qu'ils sont, pas eux qui me frustrent.

Merci encore pour votre considération. Josh

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



    class mystruct { 
    public: 
int A; 
char* B; 
char* C; 

mystruct() { 
    A = 0xFE; 
    B = new char[32]; 
    B = ""; 
    C = "test"; 
} 

void test(char *input) { 
    strncpy(B,input, strlen(input)); 
} 
    }; 

    int main(char* argv[], int argc) { 

mystruct work; 
char wtf[32]; 

    // work.A = 0xbb; 
work.test("gotchabitch!"); 
    // sprintf(wtf, "address of work is %x" , &work); 
    // strncpy(work.C,"gotchabitch!\0",strlen("gotchabitch!\0")); 
    strncpy(work.B,"gotchabitch!",strlen("gotchabitch!")); 
printf("%d;%s;%s;", work.A, work.B, work.C); 

return 0; 
    } 

Réponse à tous: Ok, je l'ai appris que lorsque vous attribuez une chaîne littérale à un char * que vous êtes vraiment dire char * const B = « quelque chose ». (n'est-ce pas différent de const char * B = quelque chose, où ce dernier est un pointeur dont l'adresse ne peut pas changer, par opposition à l'ancien qui est un pointeur vers la mémoire qui ne peut pas être changé?). De toute façon, cela explique le message d'erreur que j'ai reçu. Merci à tous pour ça.

+0

Votre analyse finale est presque exactement correcte ... mais vous avez les deux types en arrière. 'const char *' est le pointeur en mémoire qui ne peut pas être changé (comme un littéral de chaîne), tandis que 'char * const' est le pointeur qui ne peut pas être réaffecté pour pointer vers une autre mémoire, bien que vous puissiez modifier la mémoire à. –

Répondre

1
B = new char[32]; 
B = ""; 

Vous Affectez tout d'abord le pointeur retourné par new-B, vous attribuez un pointeur sur la chaîne littérale "" à B, le pointeur efficacement en écrasant retourné par new.

As Jonathan Leffler explains, littéraux de chaîne sont en lecture seule, de sorte que vous rencontrez une erreur lorsque vous essayez d'écrire à la chaîne littérale ("") a-par B.

Si vous voulez stocker la chaîne vide dans B, vous devez utiliser une fonction de bibliothèque comme strcpy() (ou de préférence, une fonction plus sûre, comme snprintf()). Dans ce cas, vous pouvez également affecter \0 à B[0], puisque c'est la même chose. En C et C++, vous ne pouvez pas affecter de tableaux (ou de chaînes C, qui ne sont que des tableaux de caractères) en utilisant =.

Idéalement, vous devriez simplement utiliser std::string au lieu de chaînes C brutes; alors vous n'avez pas à vous soucier de ce genre de chose.

1

Le problème est que lorsque vous avez essayé de le faire:

strncpy(work.C, "something", strlen(something)); 

vous copiez sur les données en lecture seule - qui ne sont pas une bonne idée. C'est parce que le pointeur, C, pointe vers une chaîne littérale; l'écrasement des littéraux de chaîne n'est pas autorisé. Des commentaires similaires s'appliquent à B - mais là aussi vous fuyez la mémoire.

Le point clé est le commentaire que vous avez fait à propos de l'erreur 'run time' et non pas 'compile time'. Ce n'est pas que le membre est inaccessible; Ce n'est tout simplement pas abusable quand vous l'avez initialisé comme vous l'avez fait.

1

L'erreur est dans la ligne:

C = "test"; 

dans le constructeur de mystruct. "test" est un pointeur vers la mémoire en lecture seule, il n'est pas prudent de l'utiliser pour initialiser un pointeur non const. La seule raison pour laquelle le compilateur n'applique pas ceci est l'énorme quantité de code C créée avant que les gens se soucient de const-correct, qui devrait être déclaré const mais ne le sont pas.

B = ""; 

est également non-sécurisée.