php_str_replace_in_subject, bug de PHP.

ViPHP
ViPHP | 4674 Messages

10 juin 2008, 12:24

Hey :),

J'ai rencontré un super bug avec PHP, et ça m'embête pas mal.
J'ouvre ma page, l'application httpd plante magistralement, EXC_BAD_ACCESS et KERN_PROTECTION_FAILURE au rendez-vous, ça démarre fort.
Je regarde le thread 0 crashed et je me rends compte que la fonction php_str_replace_in_subject pose problème. Elle dépend de php_str_replace_common, qui à son tour, dépend de zend_do_fcall_common_helper_SPEC.

Je regarde sur Internet, et notamment du côté du bug tracker de PHP et je trouve le bug 20221. Horreur, il existe depuis 2002 et il n'est pas toujours pas réparé. On trouve encore des traces de ce bug en PHP 5.0.4, je suis en 5.2.5 et le bug existe toujours.

Donc, j'ai fini par trouver où est-ce qu'il se déclenchait. À un moment donné, pas de bol, j'utilise la fonction str_replace et ça me fout tout en l'air. Je n'arrive pas vraiment à comprendre pourquoi, car je n'utilise que des chaînes (et pas des tableaux, même si une chaîne est un tableau, je pense que PHP fait la différence pour cette fonction non ?). Voilà. Mais j'ai besoin de cette fonction, alors je fais comment ? J'attends un correctif ou alors j'utilise une autre fonction ?

Merci :).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphant du PHP | 353 Messages

10 juin 2008, 13:36

As-tu un exemple de code permettant de reproduire le bug ?
Dans la doc, il semble que le bug a été corrigé :
Le comportement de cette fonction a changée. Dans les version précédentes, un bogue existait lors de l'utilisation de tableaux avec les paramètres search et replace en même temps. Les index de search qui étaient vides étaient ignorés, mais le pointeur interne de replace n'étais pas incrémenté. Cela a été corrigé en PHP 4.3.3, tout script s'appuyant sur ce bogue, doit supprimer les entrées vides avant d'appeler cette fonction pour imiter le comportement d'origine.
Ou alors je n'ai pas compris quel était le problème, ce qui est tout à fait possible.

ViPHP
ViPHP | 4674 Messages

10 juin 2008, 14:12

Non c'est un bug différent, mais je n'arrive pas à me l'expliquer.

Je cherche "\n" que je remplace par "\n " dans un objet qui contient une collection de collections. Rassurer, c'est tout à fait léger. Chaque objet est transformé en chaîne via __toString. Mais je n'ai pas ce problème avec des petites collections, seulement avec des grosses … Peut-être un problème de mémoire ? Je me questionne.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

ViPHP
ViPHP | 4674 Messages

30 juin 2008, 16:00

Aïe, toujours le même bug.
Alors, j'ai un peu fouiné et j'ai essayé plusieurs choses.

Voici d'abord le problème :
str_replace("\n", "\n  ", $element);
J'effectue cette opération afin d'intenter proprement mon code. J'ai vu que PHP prenait beaucoup de mémoire quand j'ai des chaînes assez grosses (20 ou 30 lignes de 80 caractères en gros) et que c'était une cause probable du plantage. Bien, j'essaye preg_replace mais elle prend presque 5 fois plus de mémoire, pas une bonne idée.

Je suis un peu perdu et je ne sais pas quoi faire. Je ne supporte pas l'idée que mon code soit tout pas beau (même si c'est juste histoire de 2 espaces par ci par là), et quoi que je fasse, je retombe sur ce problème de mémoire. PHP tente d'allouer plus de mémoire que le php.ini lui autorise, et paf, erreur.

Une idée ?
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Mammouth du PHP | 1668 Messages

30 juin 2008, 16:06

Bah, j'en ai bien une mais...
$element=implode("\n  ", explode ("\n", $element));
Bon c'est bof mais bon :?
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

ViPHP
ViPHP | 4674 Messages

30 juin 2008, 16:13

Déjà essayé, pareil.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Mammouth du PHP | 1668 Messages

30 juin 2008, 16:16

Bah tu aura un code dégueulasse ^^

Pour avancé : Tu avais essayé quoi comme REGEX ?
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

ViPHP
ViPHP | 4674 Messages

30 juin 2008, 16:23

Avec str_replace :
str_replace("\n", "\n  ", $element);
Avec preg_replace :
preg_replace("#\n#", "#\n  #", $element);
Original, je sais …

str_replace doit être la fonction qui prend le moins de mémoire je pense (si on compare toutes les cousines ereg, i, etc.).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Mammouth du PHP | 1668 Messages

30 juin 2008, 16:34

Et ça fait planté ton script ???
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

ViPHP
ViPHP | 4674 Messages

30 juin 2008, 16:38

Cf. mon premier message ……
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Mammouth du PHP | 1668 Messages

30 juin 2008, 16:56

tu as essayé ça :
preg_replace("#\n#", "#\n\s\s#", $element);
Je penses que c'est le fait de remplacer un caractère par le même caractère mais avec un plus...
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

ViPHP
ViPHP | 5924 Messages

30 juin 2008, 17:21

Utilise strtr() à la place de str_replace() . En principe cela devrait mieux fonctionner...

ViPHP
ViPHP | 4674 Messages

30 juin 2008, 17:40

Même problème. C'est à devenir fou.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphant du PHP | 185 Messages

30 juin 2008, 18:28

T'as fait quoi ?

Code : Tout sélectionner

strtr($chaine, array("\n" => "\n "));
?

Sinon t'as le droit à exec() ?

J'ai une version en .c si tu veux :

Code : Tout sélectionner

char *str_replace(const char* search, const char* replace, const char* str){ long i = 0; long size_search = strlen(search); long size_str = strlen(str); char *copy = (char *)malloc((size_str + 1) * sizeof(char)); char *found = copy; char *out = NULL; // -- Pour connaitre le nombre de caractères dans out, on récupère // -- le nombre de fois qu'apparait search, puis on le multiplie par // -- la différence entre la taille de la chaine de remplacement // -- et la taille de la chaine à rechercher. out = (char *)malloc((size_str + (substr_count(search, str) * (strlen(replace) - size_search)) + 1) * sizeof(char)); out[i] = '\0'; // Par mesure de sécurité. // On copie la chaine pour pouvoir la manipuler sans risques, et on fait une recherche. strcpy(copy, str); found = strstr(copy, search); while (found != NULL){ // copy = position trouvée i = (found-copy); strncat(out, copy, i); strcat(out, replace); copy += i + size_search; found = strstr(copy, search); } strcat(out, copy); free(copy); return out; }

ViPHP
ViPHP | 4674 Messages

30 juin 2008, 18:36

Uè j'ai fait ça, mais rien n'y fait :(.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).