473,416 Members | 1,726 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,416 software developers and data experts.

Smart char * class...

I need a smart char * class, that acts like a char * in all cases, but
lets you do some std::string-type stuff with it. (Please don't say to
use std::string - it's not an option...). This is my attempt at it,
but it seems to be lacking... I'm aware that strdup() is nonstandard
(and a bad idea for C++ code) - please just bear with me:

/* Assume relevant headers are included */

class char_ptr
{
char *value;

public:
char_ptr() : value(strdup("")) {}
~char_ptr() {free(value);}
char_ptr( const char *s ) : value(strdup(s?s:"")) {}

void operator= ( const char * s ) {
free( value );
value=strdup( s?s:"" );
};

Aside from ignoring the return value of strdup(), is there anything
that invokes undefined behavior in this definition? If there is not,
should the following code work or not?

char_ptr s( "Hello, world!\n" );
printf( "%s", s );

I'm aware of the very kludgy nature of this stuff; is there a (better)
way to accomplish this task? Can it be done at all?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #1
9 2183
Christopher Benson-Manica wrote:
I need a smart char * class, that acts like a char * in all cases, but
lets you do some std::string-type stuff with it. (Please don't say to
use std::string - it's not an option...).
Could you maybe explain why it's not an option?
This is my attempt at it,
but it seems to be lacking... I'm aware that strdup() is nonstandard
(and a bad idea for C++ code) - please just bear with me:

/* Assume relevant headers are included */

class char_ptr
{
char *value;

public:
char_ptr() : value(strdup("")) {}
~char_ptr() {free(value);}
char_ptr( const char *s ) : value(strdup(s?s:"")) {}

void operator= ( const char * s ) {
free( value );
value=strdup( s?s:"" );
};

Aside from ignoring the return value of strdup(), is there anything
that invokes undefined behavior in this definition? If there is not,
should the following code work or not?

char_ptr s( "Hello, world!\n" );
printf( "%s", s );
No. Passing an object to a function with variable number of arguments
is undefined. So, printf is not going to work unless you define one
more member function of 'char_ptr', 'operator const char*':

...
operator const char* () const { return value; }

.. Then you will need to do

printf("%s", (const char*)s);

Also, your class is defective: it is missing a copy constructor, which
you have to have according to the "Rule of Three".
I'm aware of the very kludgy nature of this stuff; is there a (better)
way to accomplish this task? Can it be done at all?


Keep adding functionality to your class until you get it right. Then
see which functionality you don't need, and get rid of it.

Victor
Jul 22 '05 #2
Victor Bazarov <v.********@comacast.net> spoke thus:
Could you maybe explain why it's not an option?
My boss doesn't like them, and all the code expects char *'s, and none
of it catches std::exception, so...
No. Passing an object to a function with variable number of arguments
is undefined. So, printf is not going to work unless you define one
more member function of 'char_ptr', 'operator const char*':
Ah, that's what I wanted! :)
Also, your class is defective: it is missing a copy constructor, which
you have to have according to the "Rule of Three".
That was *also* what I wanted, excellent!
Keep adding functionality to your class until you get it right. Then
see which functionality you don't need, and get rid of it.


Will do, thanks!

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #3
Christopher Benson-Manica wrote:
I need a smart char * class, that acts like a char * in all cases, but
lets you do some std::string-type stuff with it. (Please don't say to
use std::string - it's not an option...).
Why? I would really like to know.
This is my attempt at it,
but it seems to be lacking... I'm aware that strdup() is nonstandard
(and a bad idea for C++ code) - please just bear with me:

/* Assume relevant headers are included */

class char_ptr
{
char *value;

public:
char_ptr() : value(strdup("")) {}
~char_ptr() {free(value);}
char_ptr( const char *s ) : value(strdup(s?s:"")) {}

void operator= ( const char * s ) {
free( value );
value=strdup( s?s:"" );
};

I do not see undefined behaviour, but I do see that the assignment operator
is prone to self-destruct your string in

char_ptr x;
...
x = x; // <- bang. (This can occur in less abvious forms.)

Aside from ignoring the return value of strdup(), is there anything
that invokes undefined behavior in this definition? If there is not,
should the following code work or not?

char_ptr s( "Hello, world!\n" );
printf( "%s", s );

I'm aware of the very kludgy nature of this stuff; is there a (better)
way to accomplish this task? Can it be done at all?


Now, if this works then the reason would be that the compiler does not do
any type checking here. I ran a test:

#include <string.h>
#include <stdlib.h>

class char_ptr
{
char *value;

public:
char_ptr() : value(strdup("")) {}
~char_ptr() {free(value);}
char_ptr( const char *s ) : value(strdup(s?s:"")) {}

void operator= ( const char * s ) {
free( value );
value=strdup( s?s:"" );
}
};

int main ( void ) {
char_ptr s( "Hello, world!\n" );
printf( "%s", s );
}
This compiles on g++-3.4.0/Linux but segfaults. You need a cast:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

class char_ptr
{
char *value;

public:
char_ptr() : value(strdup("")) {}
~char_ptr() {free(value);}
char_ptr( const char *s ) : value(strdup(s?s:"")) {}

void operator= ( const char * s ) {
free( value );
value=strdup( s?s:"" );
}

operator const char * ( void ) const {
return value;
}
};

int main ( void ) {
char_ptr s( "Hello, world!\n" );
printf( "%s", (const char*)s );
}

This seems to work, but is flawed as pointed out above.
Now, if you need a cast anyway, why not use std::string?
Best

Kai-Uwe Bux

ps.: If you really insist, here is a version that I wrote long ago to
convince myself that I cannot do better than std::string.
#include <string>

class
minimal_string {
private:

char* data;
std::size_t size;

inline
void allocate ( size_t __size ) {
size = __size;
data = new char [ __size ];
}

inline
void deallocate ( void ) {
delete[] data;
}

inline
static
void memcopy ( const char* source, char* dest, size_t size ) {
std::char_traits<char>::copy( dest, source, size );
}

inline
void copy_string ( const char* str ) {
// WARNING: [no deallocation]
/*
| This is used in the constructor. Therefore,
| no deallocation can be done.
*/
if ( str != NULL ) {
std::size_t l ( std::char_traits<char>::length( str ) + 1 );
allocate( l );
memcopy( str, data, l );
} else {
// maybe, we should throw something ?
allocate( 1 );
*data = 0;
}
}

public:

minimal_string ( void ) {
allocate( 1 );
*data = 0;
}

minimal_string ( const char* str ) {
copy_string( str );
}

minimal_string ( const minimal_string & other ) {
std::size_t l ( other.length() );
allocate( l );
memcopy( other.data, data, l );
}

~minimal_string ( void ) {
delete [] data ;
}

const minimal_string & operator= ( const minimal_string & other ) {
if ( this != &other ) {
deallocate();
std::size_t l ( other.length() );
allocate( l );
memcopy( other.data, data, l );
}
return( *this);
}

void setString ( const char* str ) {
deallocate();
copy_string( str );
}

std::size_t length ( void ) const {
return( size );
//return( 1 + std::char_traits<char>::length( data ) );
}

operator const char* ( void ) const {
return( data );
}

}; // minimal_string
Beware, I wrote this before I knew anything about exception safe coding.
Therefore, it is very likely that this leaks memory when something is
thrown.
Jul 22 '05 #4
Christopher Benson-Manica wrote:
I need a smart char * class, that acts like a char * in all cases, but
lets you do some std::string-type stuff with it. (Please don't say to
use std::string - it's not an option...). This is my attempt at it,
but it seems to be lacking... I'm aware that strdup() is nonstandard
(and a bad idea for C++ code) - please just bear with me:

/* Assume relevant headers are included */

class char_ptr
{
char *value;

public:
char_ptr() : value(strdup("")) {}
~char_ptr() {free(value);}
char_ptr( const char *s ) : value(strdup(s?s:"")) {}

void operator= ( const char * s ) {
free( value );
value=strdup( s?s:"" );
};

Aside from ignoring the return value of strdup(), is there anything
that invokes undefined behavior in this definition? If there is not,
should the following code work or not?

char_ptr s( "Hello, world!\n" );
printf( "%s", s );

I'm aware of the very kludgy nature of this stuff; is there a (better)
way to accomplish this task? Can it be done at all?


I am also in a situation where std::string is not an option. I have created a
AsciiString class which I have been using in production code for a year now. I
used Doxygen to make pretty HTML docs. There are some pretty nifty features in
it. Almost as good as Qt's QString. If you are interested, I can fire off the
code and docs to you.

~Shea M.
Jul 22 '05 #5
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:PD**************@newsread1.dllstx09.us.to.ver io.net...
<snip>
...
operator const char* () const { return value; }

. Then you will need to do

printf("%s", (const char*)s);


To the OP: Another, IMHO slightly safer, option is to write a member
function like std::string::c_str().

--
David Hilseer
Jul 22 '05 #6

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message news:cg5l95
My boss doesn't like them,
Emotions shouldn't play into it.
and all the code expects char *'s
The c_str() function provides this
, and none of it catches std::exception, so...
and this makes a difference how? The only thing in std::string that's going
to throw is the allocation and if you're going to dynamically allocate the
char's, they're just as likely to throw.
No. Passing an object to a function with variable number of arguments
is undefined. So, printf is not going to work unless you define one
more member function of 'char_ptr', 'operator const char*':


Ah, that's what I wanted! :)


Further, you're going to have to force the conversion in things like printf
to convert to that.

Jul 22 '05 #7
Ron Natalie <ro*@sensor.com> spoke thus:
Emotions shouldn't play into it.
Well, no; I suppose the better statement would have been "he doesn't
trust them", and given the horrific excuse for an implementation we're
using, his mistrust isn't completely misplaced...
The c_str() function provides this
Right, but no one (besides me) is willing to call it explicitly.
and this makes a difference how? The only thing in std::string that's going
to throw is the allocation and if you're going to dynamically allocate the
char's, they're just as likely to throw.
Said implementation has been known to throw for simple operations such
as assigning the empty string to a std::string.
Further, you're going to have to force the conversion in things like printf
to convert to that.


To be standards-compliant, at least; the bulk of the code is so
non-standard (partly to comply with the whims of said implementation)
that switching to a reasonable implementation would be prohibitively
time-consuming and expensive anyway.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #8

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message news:cgcpuv$rc7

Right, but no one (besides me) is willing to call it explicitly.
In your example, even with a char* conversion operator, you're going
to have to do SOMETHING explicitly. The implicit conversions just
make it more likely to screw up
and this makes a difference how? The only thing in std::string that's going
to throw is the allocation and if you're going to dynamically allocate the
char's, they're just as likely to throw.
Said implementation has been known to throw for simple operations such
as assigning the empty string to a std::string.


I doubt that highly. What most likely happens is you invoke undefined behavior
for passing a null char* pointer to the one of the functions in std::string that take
a char*. Doesn't matter if you are catching std::exception or not, the behavior
isn't defined at all.
Further, you're going to have to force the conversion in things like printf
to convert to that.


To be standards-compliant, at least; the bulk of the code is so
non-standard (partly to comply with the whims of said implementation)
that switching to a reasonable implementation would be prohibitively
time-consuming and expensive anyway.

Unless you're convinced that a particular function is known to be bad, all you
are doing is generating a whole mess of new problems by defining your own half-assed
attempts to reproduce what has already been written.

Jul 22 '05 #9
Ron Natalie <ro*@sensor.com> spoke thus:
In your example, even with a char* conversion operator, you're going
to have to do SOMETHING explicitly. The implicit conversions just
make it more likely to screw up
I suppose so...
I doubt that highly. What most likely happens is you invoke undefined behavior
for passing a null char* pointer to the one of the functions in std::string that take
a char*. Doesn't matter if you are catching std::exception or not, the behavior
isn't defined at all.
This is pre-modern STL here, so you might not want to doubt it quite
so highly. I'm quite positive of this, as much of this
implementation's stream library simply does not work like my
references say it should (as I posted here several months ago).
Unless you're convinced that a particular function is known to be bad, all you
are doing is generating a whole mess of new problems by defining your own half-assed
attempts to reproduce what has already been written.


Ron, believe me when I say that you're preaching to the choir here;
you need to talk to my boss :)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: lokb | last post by:
Hi, I have a structure which and defined a smart pointer to the structure. /* Structure of Begin Document Index Record */ typedef struct BDI_Struct{ unsigned char rname; unsigned short int...
4
by: Matthias Kaeppler | last post by:
Hi, I'm having a hard time figuring out how I can initialize a smart pointer based on a certain condition: if something then ptr = 0; // init with NULL else ptr = new XYZ; // init with a...
6
by: zl2k | last post by:
hi, When I considered about preventing memory leaking, the method came up to my mind is using boost smart pointer if possible (use stl::vector instead of type, use smart pointer whenever declare...
92
by: Jim Langston | last post by:
Someone made the statement in a newsgroup that most C++ programmers use smart pointers. His actual phrase was "most of us" but I really don't think that most C++ programmers use smart pointers,...
3
by: Nindi73 | last post by:
Hi, I am in need of a deep copy smart pointer (Boost doesn't provide one) which doesnt require the contained types to have a virtual copy constructor. I wrote a smart pointer class that I think...
11
by: Nindi73 | last post by:
A few days a ago I posted my code for a deep copy pointer which doesn't require the pointee object to have a virtual copy constructor. I need help with checking that it was exception safe and...
3
by: mati-006 | last post by:
Hi, I think the code will be the best way to explain what I mean: #include "arglib/arg_shared.h" class base { public: base() {} virtual ~base() {} };
8
by: Simon L | last post by:
Pointer mismanagement is a big cause of bugs in software that I work on. I decided to invest a little time into having a look at auto_ptr and other smart pointers but I don't see how they'll save...
1
by: Rune Allnor | last post by:
Hi all. I am sure this is an oldie, but I can't find a useful suggestion on how to solve it. I have a class hierarchy of classes derived from a base class. I would like to set up a vector of...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.