Strings, seg faults, and memory

Though not directly an sdl question I have come to need dynamic strings
to work with sfont and things with sdl, I figgured you guys would be
able to answer this rather simply.

I am used to declaring and reading/writing to a string in this
fassion…

char* str;
sprintf (str,"%i",1234);
etc…

However I find that segfaults, as does any attempt to write to char*
post declaration as apparently gcc makes it a const char* instead.
However if I do a calloc and specify the specific size it will be fine,
as such…

char* str = (char*)calloc(10,sizeof(char));

so the question is, to I have to alloc all my strings? or is there a
better/simpler way of dealing with it?–
Matt Pruett <@Matt_Pruett>

Hello Matt,On Sat, 25 Jun 2005 23:54:12 -0700 Matt Pruett wrote:

Though not directly an sdl question I have come to need dynamic strings
to work with sfont and things with sdl, I figgured you guys would be
able to answer this rather simply.

I am used to declaring and reading/writing to a string in this
fassion…

char* str;
sprintf (str,"%i",1234);
etc…

However I find that segfaults, as does any attempt to write to char*
post declaration as apparently gcc makes it a const char* instead.
However if I do a calloc and specify the specific size it will be fine,
as such…

char* str = (char*)calloc(10,sizeof(char));

so the question is, to I have to alloc all my strings? or is there a
better/simpler way of dealing with it?

You’re right, that’s a C question (maybe you’re interesting in posting to
linux-c-programming, see http://vger.kernel.org/majordomo-info.html).

Defining a char* doesn’t allocate any room for your string manipulation
at all, it just creates a pointer to what you have to allocate, then.

Using malloc/calloc is the right way, but you might find more convenient to
use arrays of chars like this:

char str[100];
sprintf(str, “%i”, 1234);

Take care of not buffer overflowing str[] when putting chars in it. str
allows storing 100 chars, from str[0] to str[99], including a trailing zero
(storing “foo” in it would eat 4 chars), so don’t put more than 100 chars in
it. See snprintf too (man printf), which allows storing chars in str, w/ a
size limit for security.

Regards,


wwp

I am used to declaring and reading/writing to a string in this fassion…

char* str;
sprintf (str,"%i",1234);
etc…

However I find that segfaults, as does any attempt to write to char*
post declaration as apparently gcc makes it a const char* instead.

No, it’s because you declare a pointer to char, but it doesn’t really
point to a bunch of chars that actually belong to you.

However if I do a calloc and specify the specific size it will be fine, as such…
char* str = (char*)calloc(10,sizeof(char));
so the question is, to I have to alloc all my strings? or is there a better/simpler way of dealing with it?

Yes, you do have to make sure your pointers point to something, but
there’s no need to make them dynamic. The following also works :

char str[1024];
sprintf(str, “%i”, 1234);
–Gabriel

You really should use snprintf though.

#define STR_LEN 1024

char str[STR_LEN];
sprintf(str, STR_LEN, “%i”, 1234);

Writing on strings without locking the bounds is evil.

  • SROn 6/26/05, Gabriel wrote:

char str[1024];
sprintf(str, “%i”, 1234);

Argh, should’ve been “snprintf” here. I just screwed up the whole
point of my post. Way to go, me.

  • SROn 6/26/05, Simon Roby <@Simon_Roby> wrote:

sprintf(str, STR_LEN, “%i”, 1234);

char* str = (char*)calloc(10,sizeof(char));

so the question is, to I have to alloc all my strings? or is there a
better/simpler way of dealing with it?

I use a function called Va(), which allows you to do this on the spot,
thereby creating less verbose code. This is tested on Win32, Linux and
OS X.

The memory for the strings is static, and part of the Va() function
itself. The result of too many recursions is undefined.

#define MAX_RECURSIONS 4
#define MAX_LONG_STRING 4096

char *Va( char *format, … )
{
static char string[MAX_RECURSIONS][MAX_LONG_STRING];
static int callNum = 0;

 /* Begin arg printing */

#ifdef WIN32

 va_list ap;
 va_start( ap, format );
int len = _vscprintf( format, ap ) + 1;
if ( len > MAX_LONG_STRING )
{
	printf("Overflow: Message too large.\n");
	return NULL;
}
 vsprintf( string[callNum], format, ap );
 va_end( ap );

#else

 va_list ap;
 va_start( ap, format );
 if ( vsnprintf( string[callNum], MAX_LONG_STRING, format, ap ) > 

MAX_LONG_STRING )
{
printf(“Overflow: Message too large.\n”);
return NULL;
}
va_end( ap );

#endif
/* End arg printing */

 int oldCall = callNum;
 callNum++;
 if ( callNum >= MAX_RECURSIONS )
     callNum = 0;

 return string[oldCall];

}

/* Sample usage */
void SetName( char *nameStr );

SetName( Va("%s the %ser", name, titleVerb) );

Doesn’t that give you huge memory leaks if you use that frequently?

JoshOn 6/27/05, Michael L. wrote:

char* str = (char*)calloc(10,sizeof(char));

so the question is, to I have to alloc all my strings? or is there a
better/simpler way of dealing with it?

I use a function called Va(), which allows you to do this on the spot,
thereby creating less verbose code. This is tested on Win32, Linux and
OS X.

The memory for the strings is static, and part of the Va() function
itself. The result of too many recursions is undefined.

#define MAX_RECURSIONS 4
#define MAX_LONG_STRING 4096

char *Va( char *format, … )
{
static char string[MAX_RECURSIONS][MAX_LONG_STRING];
static int callNum = 0;

 /* Begin arg printing */

#ifdef WIN32

 va_list ap;
 va_start( ap, format );
    int len = _vscprintf( format, ap ) + 1;
    if ( len > MAX_LONG_STRING )
    {
            printf("Overflow: Message too large.\n");
            return NULL;
    }
 vsprintf( string[callNum], format, ap );
 va_end( ap );

#else

 va_list ap;
 va_start( ap, format );
 if ( vsnprintf( string[callNum], MAX_LONG_STRING, format, ap ) >

MAX_LONG_STRING )
{
printf(“Overflow: Message too large.\n”);
return NULL;
}
va_end( ap );

#endif
/* End arg printing */

 int oldCall = callNum;
 callNum++;
 if ( callNum >= MAX_RECURSIONS )
     callNum = 0;

 return string[oldCall];

}

/* Sample usage */
void SetName( char *nameStr );

SetName( Va("%s the %ser", name, titleVerb) );


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

I use a function called Va(), which allows you to do this on the spot,
thereby creating less verbose code. This is tested on Win32, Linux and
OS X.

I use another one that (I think) is more simple and (the most important) has
no limit in the string lenght !
The only thing is that it will slow your game if you use it a lot of times
in a frame.
There is no bad code in my mail, it’s just in html cauz i copied the code
and now it’s in color ^^

/ This function is taken from a gcc manual page example and adapted
to my needs.

  • FTSExp is like nothing.

  • Pompei2 at gmail.com
    /
    FTSExp char *MyAllocSPrintf( const char *fmt, … )
    {
    va_list ap;
    char * p = NULL;
    int size = 2,
    n = 0;

    / AllocStr simply allocs a char * (with malloc) and fills it with ‘\0’ s /
    if( NULL == (p = AllocStr( size )) )
    return NULL;
    while( 1 ) {
    / Try to print in the allocated space. /
    va_start( ap, fmt );
    n = vsnprintf( p, size, fmt, ap );
    va_end( ap );#ifndef _WIN32
    / If that worked, return the string. /
    if (n > -1 && n < size)
    return p;
    / Else try again with more space. /
    if (n > -1)
    size = n+1;
    else / n <= -1 /
    size *= 2;
    #else / NOT WIN32 /
    / If that worked, return the string. /
    if (n > -1 && n < size - 1)
    return p;
    / Else try again with more space. /
    if (n > -1)
    size += 1;
    else / n <= -1 /
    size *= 2;
    #endif / NOT_WIN32 /
    / MyRealloc is just like the normal realloc. /
    if( NULL == (p = (char *)MyRealloc( p, size )) )
    return NULL;
    }
    }

/ How to use it ?? it’s very simple: /

char *psz = NULL;
psz = MyAllocSPrintf( “Yeah, it %s !\nblablabla %d”, “works perfectly”, 12345 );

/ Do your stuff … */
*

if( psz ) {
free( psz );
psz = NULL;
}

P.O.M.P.E.I. du 47-20