[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Chicken-users] c-string return question
From: |
Jörg F . Wittenberger |
Subject: |
Re: [Chicken-users] c-string return question |
Date: |
13 Oct 2011 19:09:32 +0200 |
On Oct 13 2011, John Cowan wrote:
Jörg F. Wittenberger scripsit:
(define integer->utf8string
(foreign-lambda*
c-string ((unsigned-integer ch))
"static C_uchar off[6]={0xFC,0xF8,0xF0,0xE0,0xC0,0x00};
int size=5; C_uchar buf[7];
buf[6]='\\0';
if (ch < 0x80) {
buf[5]=ch;
} else {
buf[size--]=(ch&0x3F)|0x80; ch=ch>>6;
while (ch) { buf[size--]=(ch&0x3F)|0x80; ch=ch>>6; }
/* Write the size information into the first byte */
++size;
buf[size]=off[size]|buf[size];
}
return(buf+size);
"))
This code is not good C, because it returns a pointer into a stack
frame which has already been exited. It may just so happen that
there is still a correct value there, but there are no guarantees.
I'd guess that the corruption happens when there is a minor GC.
See http://c-faq.com/~scs/cclass/int/sx5.html .
Wait!
The chicken manual does not mention this restriction. For a reason.
When you read the expanded C code as Chicken produces,
you will find, that it does through some magic to make sure
this restriction shall not apply.
(Watch out for C_cblock and C_cblockend #defines in chicken.h
, which depend on the C compiler in use.)
It does a local #define return(x) to insert a block wherein it
saves the to-be-returned string *before* the actual return statement
is seen by the C compiler.
1.) static C_uchar buf[7];
^^^^^^
does the trick.
That's absolutely the Right Thing. You are now returning a pointer to
the static data region, which will always be available.
Not exactly. While your explanation of my reasoning how to circumvent
the none-working situation is correct, this means that
the trick as deployed in the Chicken source does not work under certain
C compilers.
Best Regards
/Jörg
Re: [Chicken-users] c-string return question, Jim Ursetto, 2011/10/13