🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.python
3 messages
3 total messages Started by kenubi Wed, 18 Nov 2009 17:13
Python3,c-api,PyUnicode_Decode - niszczy wskaźnik?
#26951
Author: kenubi
Date: Wed, 18 Nov 2009 17:13
43 lines
1959 bytes
Napisałem taką funkcję w swoim module (C) dla testu:
Python 3.1.1

---------------------------------------
wklejam:

static PyObject * py_test1(PyObject *self, PyObject *args)
{
	PyObject	*SO,*temp;
	char		*s;
	
    if (!PyArg_ParseTuple(args,"U",&SO)) return NULL;
	
	temp = PyUnicode_AsEncodedString(SO,"iso8859-2","replace");
	if ( temp == NULL ) return NULL;
	s = PyBytes_AsString(temp);
	if ( s == NULL ) return NULL;
	Py_DECREF(temp);

	printf("<%s>\n",s);
	temp = PyUnicode_Decode( s, strlen(s), "iso8859-2","strict");
	printf("[%s]\n",s);

	return 	Py_BuildValue("s",s);
}

----------------------------------
jak wołam dla ciągu: "ala,ma,kota    " (4 spacje za kota)
to dostaję:
"<ala,ma,kota    >"
"[ala,ma,kota    ]"
'ala,ma,kota      '

a jak dla ciągu: "ala,ma,kota     " (5..12 spacji za kota,dla 13 jest O.K.)
to dostaję:
"<ala,ma,kota     >"
"[8]"
'8'
?? PyUnicode_(tak, bez jego wywołania nic się nie dzieje) zniszczył 
zawartość źródła? 
To jest Bug czy ja czegoś nie zrozumiałem?
pozdrawiam
Re: Python3,c-api,PyUnicode_Decode - niszczy wskaźnik?
#26952
Author: kenubi
Date: Thu, 19 Nov 2009 10:14
8 lines
1207 bytes
kenubi wrote:

> s = PyBytes_AsString(temp);
> Py_DECREF(temp);

OK, zapomiałem a dokumentacja przypomniała, że jest zwracany wskaźnik do 
wewnętrznego bufora (tu obiektu temp) a ja go zaraz potem "niszczę" 
(DECREF). Także nowy dzień, świeże spojrzenie, rozwiązało problem.
Re: Python3,c-api,PyUnicode_Decode - niszczy wskaźnik?
#26953
Author: Rob Wolfe
Date: Thu, 19 Nov 2009 10:53
63 lines
2589 bytes
kenubi <nono@no.pl> writes:

> Napisałem taką funkcję w swoim module (C) dla testu:
> Python 3.1.1

Błąd tkwi w Twoim kodzie. Patrz niżej.

>
> ---------------------------------------
> wklejam:
>
> static PyObject * py_test1(PyObject *self, PyObject *args)
> {
> 	PyObject	*SO,*temp;
> 	char		*s;
> 	
>     if (!PyArg_ParseTuple(args,"U",&SO)) return NULL;
> 	
> 	temp = PyUnicode_AsEncodedString(SO,"iso8859-2","replace");
> 	if ( temp == NULL ) return NULL;
> 	s = PyBytes_AsString(temp);

Tu pobierasz wskaźnik do wewnętrznego bufora obiektu `temp`
a nie jego kopię [1]_.

> 	if ( s == NULL ) return NULL;
> 	Py_DECREF(temp);

A tu zwalniasz pamięć obiektu `temp` wraz z jego wewnętrznym buforem.
Wszystko co się dalej dzieje leży w rękach GC i przypadkowej
zawartości bufora, na który wskazuje `s`.

>
> 	printf("<%s>\n",s);
> 	temp = PyUnicode_Decode( s, strlen(s), "iso8859-2","strict");
> 	printf("[%s]\n",s);
>
> 	return 	Py_BuildValue("s",s);
> }
>
> ----------------------------------
> jak wołam dla ciągu: "ala,ma,kota    " (4 spacje za kota)
> to dostaję:
> "<ala,ma,kota    >"
> "[ala,ma,kota    ]"
> 'ala,ma,kota      '
>
> a jak dla ciągu: "ala,ma,kota     " (5..12 spacji za kota,dla 13 jest O.K.)
> to dostaję:
> "<ala,ma,kota     >"
> "[8]"
> '8'
> ?? PyUnicode_(tak, bez jego wywołania nic się nie dzieje) zniszczył 
> zawartość źródła? 
> To jest Bug czy ja czegoś nie zrozumiałem?

Dlatego tak kocham ręczne zarządzanie pamięcią.
Błąd popełniony w jednym miejscu może doprowadzić do wysnuwania
szalonych teorii w innym. ;)

.. [1] http://docs.python.org/3.1/c-api/bytes.html?highlight=pybytes_asstring#PyBytes_AsString

RW
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads