0

Tout d'abord, il ne s'agit pas d'un duplicate. Ma question est de savoir comment le faire avec la mémoire dynamique. La raison pour laquelle ceci est distinct est parce que mon delete[] est suspendu.Comment copier une chaîne terminée par un caractère non nul en mémoire dynamique

Alors, voici ce que j'ai:

class PacketStrRet { 
    public: 
    PacketStrRet(char p_data[], int p_len) : len(p_len) { 
     data = new char[p_len]; 
     memcpy(data, p_data, p_len * sizeof(char)); 
    } 

    ~PacketStrRet() { 
     delete[] data; 
     data = nullptr; 
    } 

    char* data; 
    int len; 
}; 

Et oui, je suis conscient que mon code n'utilise les meilleures pratiques. Je vais le nettoyer plus tard.

Le problème que j'ai est dans le DTOR. Cette suppression est suspendue pour toujours. Les données transmises au CTOR sont et non mémoire dynamique, donc je dois le rendre dynamique pour que les choses ne soient pas hors de portée. p_len contient la bonne quantité de données, il n'y a donc pas de problème. De ce que j'ai lu, memcpy semble être le coupable le plus probable ici. Alors, comment puis-je copier une chaîne qui n'est pas terminée par un caractère nul en mémoire dynamique, et être capable de la supprimer plus tard?

Merci.

+0

Cela ressemble également à une violation des règles de trois. –

+0

@KerrekSB, pouvez-vous mettre cela dans une réponse? – David

+0

Ça a l'air ok. Vous pouvez supprimer le * sizeof (char) dans le memcpy tant que vous n'avez pas une plate-forme bizarre ou l'ajouter aussi à l'invocation 'new', mais cela ne devrait pas faire de différence. Je suppose que l'erreur est ailleurs. – Matthias247

Répondre

-1

Essayez d'utiliser std :: copy(). Ce sera comme ceci: std::copy(p_data, p_data + p_len, data).

+0

En quoi est-ce différent de 'memcpy', mis à part beaucoup plus de frais généraux? – David

+0

@David - 'std :: copy' n'a pas" beaucoup plus d'overhead ". –

1

Le problème n'est pas la suppression, seulement tout ce qui vient avant et même ce serait bien s'il n'y avait aucun problème.

class PacketStrRet { 
    // Use RAII 
    std::unique_ptr<char> data; // I own this data and will destroy it. 
    // now the parent class is also only movable, use shared_ptr if you can't live with that. 
    int len; 

    public: 
    PacketStrRet(
     // <RED ALERT> 
     char p_data[], int p_len // user can lie to us. 
     // </RED ALERT> 
     ) try : // function try block, se 1) 
      len(p_len), data(new char[p_len]) { 
     memcpy(data, p_data.get(), p_len * sizeof(char)); 
    } catch(const std::exception& e) { 
     std::cerr << "arg=" << arg << " failed: " << e.what() << '\n'; 
    } 

    ~PacketStrRet() { 
     // unique_ptr takes care of memory management and garbage collection. 
    } 
    // access functions 
}; 

Maintenant, les erreurs possibles que vous pourriez faire pour faire exploser le code.

Vous auriez pu copier l'objet, en faisant essentiellement deux pointeurs raw propriétaires des mêmes données. Cela exploserait à la suppression, vous pouvez utiliser memory-sanitizer/valgrind pour confirmer que cela arrive. Utilisez des pointeurs intelligents pour vous éviter le problème, le pointeur unique devrait provoquer une erreur de compilation si vous avez essayé de copier, sauf si vous memcpy la structure entière en ignorant les constructeurs de copie/affectation.

Vous pourriez donner la mauvaise lande au constructeur, quelle est la source des données et len? Valgrind/memory-sanitizer peut vous sauver.

La corruption de la mémoire peut se produire dans un endroit totalement différent. Valgrind/memory-sanitizer peut vous sauver. Dans le cas où valgrind mem-san est trop, vous pouvez essayer de faire une vérification pour la double suppression, si vous faites un compteur dans c'tor et d'or et si jamais il passe au négatif, vous avez votre erreur.

Dans cette classe vous avez au moins manquant un constructeur de copie. Vérifiez la règle de 3, 5, 7 et 0 (zéro) pour savoir combien vous avez besoin.

1) http://en.cppreference.com/w/cpp/language/function-try-block