Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ std::string and NULL const char*

Tags:

c++

string

null

I am working in C++ with two large pieces of code, one done in "C style" and one in "C++ style".

The C-type code has functions that return const char* and the C++ code has in numerous places things like

const char* somecstylefunction();
...
std::string imacppstring = somecstylefunction();

where it is constructing the string from a const char* returned by the C style code.

This worked until the C style code changed and started returning NULL pointers sometimes. This of course causes seg faults.

There is a lot of code around and so I would like to most parsimonious way fix to this problem. The expected behavior is that imacppstring would be the empty string in this case. Is there a nice, slick solution to this?

Update

The const char* returned by these functions are always pointers to static strings. They were used mostly to pass informative messages (destined for logging most likely) about any unexpected behavior in the function. It was decided that having these return NULL on "nothing to report" was nice, because then you could use the return value as a conditional, i.e.

if (somecstylefunction()) do_something;

whereas before the functions returned the static string "";

Whether this was a good idea, I'm not going to touch this code and it's not up to me anyway.

What I wanted to avoid was tracking down every string initialization to add a wrapper function.

like image 537
pythonic metaphor Avatar asked Nov 12 '09 17:11

pythonic metaphor


3 Answers

Probably the best thing to do is to fix the C library functions to their pre-breaking change behavior. but maybe you don't have control over that library.

The second thing to consider is to change all the instances where you're depending on the C lib functions returning an empty string to use a wrapper function that'll 'fix up' the NULL pointers:

const char* nullToEmpty( char const* s)
{
    return (s ? s : "");
}

So now

std::string imacppstring = somecstylefunction();

might look like:

std::string imacppstring( nullToEmpty( somecstylefunction());

If that's unacceptable (it might be a lot of busy work, but it should be a one-time mechanical change), you could implement a 'parallel' library that has the same names as the C lib you're currently using, with those functions simply calling the original C lib functions and fixing the NULL pointers as appropriate. You'd need to play some tricky games with headers, the linker, and/or C++ namespaces to get this to work, and this has a huge potential for causing confusion down the road, so I'd think hard before going down that road.

But something like the following might get you started:

// .h file for a C++ wrapper for the C Lib
namespace clib_fixer {
    const char* somecstylefunction();
}


// .cpp file for a C++ wrapper for the C Lib
namespace clib_fixer {
    const char* somecstylefunction() {
        const char* p = ::somecstylefunction();

        return (p ? p : "");
    }
}

Now you just have to add that header to the .cpp files that are currently calling calling the C lib functions (and probably remove the header for the C lib) and add a

using namespace clib_fixer;

to the .cpp file using those functions.

That might not be too bad. Maybe.

like image 91
Michael Burr Avatar answered Oct 21 '22 04:10

Michael Burr


Well, without changing every place where a C++ std::string is initialized directly from a C function call (to add the null-pointer check), the only solution would be to prohibit your C functions from returning null pointers.

In GCC compiler, you can use a compiler extension "Conditionals with Omitted Operands" to create a wrapper macro for your C function

#define somecstylefunction() (somecstylefunction() ? : "")

but in general case I would advise against that.

like image 27
AnT Avatar answered Oct 21 '22 04:10

AnT


I suppose you could just add a wrapper function which tests for NULL, and returns an empty std::string. But more importantly, why are your C functions now returning NULL? What does a NULL pointer indicate? If it indicates a serious error, you might want your wrapper function to throw an exception.

Or to be safe, you could just check for NULL, handle the NULL case, and only then construct an std::string.

const char* s = somecstylefunction();
if (!s) explode();
std::string str(s);
like image 30
Charles Salvia Avatar answered Oct 21 '22 06:10

Charles Salvia