Legszebb öröm a káröröm

(Felülről lefelé bővül)

20160918.1947
Oszt úgy tűnik, nem különbözik. Akkor mi ez a kavarás a refcounter refaktorálásával, ami miatt az oci8 működése vagy nem-működése a hívó jóindulatának függvényévé válik?

És még itt van az a kérdés (bár itt off-topik), hogy hogyan van a NCHAR-ok támogatása... van egy olyan tippem, hogy sehogy, vagyis ami belefér a NLS_CHARACTERSET és a NLS_LANG metszetébe, az jól jár, a többi megy a levesbe.

20160918.1934
Namost ha ez így igaz, akkor akár az alábbi kód is másképp működhet php5-ben és php7-ben:


$a= 100;
$aref= &$a;
$a= 'stringvalue';
xdebug_debug_zval ('$a');
xdebug_debug_zval ('$aref');

20160918.1728
Sőt, most már úgy látom, hogy egy jól ismert dologról van szó, ami a referenciaszámolás megváltoztatása miatt elvileg is megoldhatatlan php7/oci8 oldalról, a hívónak kell ügyelnie a változó+érték 'meglétére'

From the dev who analyzed this:

"Reason for this new behavior in PHP 7 is that, unlike in PHP 5.6, zval (_zend_value) in PHP 7.0 is no more have reference count field. Only its values field (zend_value) has reference count field.

Since we store the placeholder (i.e., zval variable) [not its content (zend_value)] in php_oci_bind structure, it gets overwritten when oci_bind_by_name() is called with same variable and different content in it."

https://bugs.php.net/bug.php?id=71148
https://bugs.php.net/bug.php?id=71947

20160917.1958
Mindezek alapján írtam ezt a megjegyzést.

20160917.1921
Hasznos ez az 'xdebug_debug_zval', így már nagyjából látszik, hogy mi történik. Namostan lassan vissza kellene térni az eredeti problémára, különös tekintettel erre: oci_bind_by_name, ezen belül is a harmadik paraméterre (mixed &$variable). Ugyebár ez azért kell változó legyen, mert a bind változó lehet 'in', de lehet 'in-out' típusú is, az utóbbinál a kijövő érték nyilván egy változóba kell kerüljön.

Én magam azt hinném, hogy a 'bind' után a változónak megnő a refcount-ja, hogy az érték ne vesszen el a semmiben; de lehet, hogy tévedek, mert ilyesmiket vélek olvasni:

A bind call tells Oracle which memory address to read data from. For IN binds that address needs to contain valid data when oci_execute() is called. This means that the variable bound must remain in scope until execution. If it doesn't, unexpected results or errors such as "ORA-01460: unimplemented or unreasonable conversion requested" may occur. For OUT binds one symptom is no value being set in the PHP variable.

20160917.0738
Találtam egy ilyet Julien Pauli How PHP manages variables
Ott meg ezt ajánlják, majd kipróbálom: https://xdebug.org/

20160916.1106
A probléma talán a referenciaszámlással és a referenciákkal függ össze. Természetesen erről így nem lehet beszélni, mert nulla időn belül összekavarjuk a kettőt, ezért most az &at &szimbólummal jelölt dolgot elnevezzük pointernek.

Tehát, ha $arr2=$arr1 értékadással lemásolunk egy tömböt, akkor az elemek nem másolódnak, csak a az új tömbben lesznek referenciák a régi elemekre. (Ha írni akarunk az elemekbe, akkor beindul a copy-on-write mechanizmus.) Ha viszont pointer mutat az $arr1 valamely elemére, azzal egycsapásra mit sem törődik a másolás, a pointer a kettős referenciájú elemre mutat továbbra is. Ha most jön az értékadás, akkor mintha a copy-on-write nem történne meg a pointer létezése miatt.

20160916.1038
További tesztek során kiderült, hogy az előbbi a valós helyzet leegyszerűsítése; valamint egy kis keresgélés azt mutatja, hogy ez egy jól ismert jelenség (pl) -- nem mondom, hogy hiba, ugyanis a hibákat ki szokás javítani.

20160916.0955
Most azt mondanám, hogy ez az utasítás: $x = &$brray1[1] igazából ezt csinálja:


$x = $brray1[1];
$brray1[1]= &$x;

Természetesen nem azt mondom, hogy ez hiba. Csak azt, hogy nem találom intuitívnek.

20160916.0925
Itten az első felhasználói hozzászólás olyan jelenséget ír le, amit kicsinyes emberek akár hibának is nevezhetnek... Vagy legalábbis azt mondhatnák, hogy az egyes featurák nem ortogonálisak: lehet használni referenciákat, lehet használni tömböket, de ha a kettőt kombináljuk, akkor esetleg más történik, mint amit gondolni vélük. (egyformán működik 5.6.25-ben és 7.0.10-ben)


$ ./oci_reftest_dave.php
Normális eset, tömb-másolás, a másolatot rontjuk el: 2->22
array1=array(2) {
  [0]=> int(1)
  [1]=> int(2)
}
array2=array(2) {
  [0]=> int(1)
  [1]=> int(22)
}

Referenciával súlyosbított eset.
A referencia az első tömbre kellene mutasson: $x = &$brray1[1].
brray1=array(2) {
  [0]=> int(1)
  [1]=> &int(22)
}
brray2=array(2) {
  [0]=> int(1)
  [1]=> &int(22)
}
x=int(22)

Most elrontjuk a referencia értékét: $x=1968
brray1=array(2) {
  [0]=> int(1)
  [1]=> &int(1968)
}
brray2=array(2) {
  [0]=> int(1)
  [1]=> &int(1968)
}
x=int(1968)

20160915
... mert nincs benne irigység. Akarom mondani, más is problémázik a php7/oci8 kombinációval:
https://bugs.php.net/bug.php?id=73080

Ami azt illeti, már ez sem egészen nyilvánvaló számomra:


function param_out (&$outpar) {
    $outpar= 1968;
}

param_out (100);

Szerk: ez jó, korrektül hibakiír:
Fatal error: Only variables can be passed by reference in /local/home/projects/devel/phptest/oci_reftest.php on line 7

Hozzászólások

Kéne forkolni a php-t és csinálni belőle egy értelmes nyelvet. Tudom, kicsit flame szagú, de valójában ezen már régóta gondolkozom, és ha értenék is hozzá, talán meg is léptem volna, hátha mások se tartották volna hülyeségnek.

A PHP szerintem alapjában véve jó nyelv sok butasággal, régmúltból nyakunkon maradt dolgokkal, amik logikátlanok, inkonzisztenciát okoznak, stb, Ezek kidobásra vagy megváltoztatásra szorulnának. Csak hát ezt nem lépi meg senki a PHP fejlesztői közül, mert a visszafele kompatibilitás úgy tűnik fontosabb. A Hack nyelvnél se volt fontos ezeket megváltoztatni sajnos, pedig abban is nagyon bíztam :)

"Minek?"

Mert emberek éveket öltek bele abba, hogy megtanulják, kiismerjék, profik legyenek.

Nyilván eldobom X évnyi tapasztalatomat, gyakorlatomat ami a PHP-hez köt, és ismét kezdőként belevetem magam a Python vagy Ruby fejlesztésbe, és amíg felzárkózom addig addig pedig türelemre intem a főnökeimet :)

Egyébként semmi baj azzal ha az ember megismer több nyelvet, én is szoktam kalandozni mindenfelé. De egy élet kevés lenne a fejlesztés minden területén profi lenni minden nyelvből, kiismerni minden keretrendszert, stb...

Ráadásul azt sem mondtam, hogy a PHP nem tetszik. Elég sok dolog tetszik akár nyelvi akár architekturális megoldásokat tekintve. DE tény, hogy sok dolog nincs átgondolva, és sok dolgon lehetne változatni kicsit bátrabb átalakítással, ami jobbá tenné a PHP fejlesztők életét. Miért ne?

Mer annak örülne a főnököd, ha a phpt próbálnád patkolni? (Tippre egy programnyelv karbantartása "kicsit" nagyobb meló, mint amit egy python/perl/ruby/akármi megismerésébe kéne ölni -- itt majd biztos megköveznek, de elég hasonlóak ezek :) -- ráadásul egy hangyafasznyit más típusú ismereteket igényel, mint átállni egy másik webes framewörkre.)

"Mer annak örülne a főnököd, ha a phpt próbálnád patkolni?"

Nem tudom. Ismerve, végülis... na de nyilván nem ezért fizetnek. Ahogy azért sem, hogy új nyelveket tanulgassak, amikor már tudok egy olyat amiben tökéletesen el tudom végezni a dolgomat. Valójában nem is gondoltam arra, hogy ilyesmit munkaidőben végeznék. Arra sem, hogy egyáltalán nekiállnék, hiszen nem értek hozzá.

de én jobbat akarok :P

Komolyra fordítva látom a rációt abban hogy minimális ráfordítással (sok refaktoring főleg, némi átalakítással lehetne a meglévő PHP közösség kezébe adni egy sokkal jobb nyelvet, amit már majdnem ismernek, szerintem mindenki csak jól járna vele.

Note to Self: ki kellene próbálni 8.4-ben, megjavult-e.