georoot
georoot

Reputation: 3617

String to const char * in c++ puts garbage at end

I have a struct that needs to store const char * for later. The string gets destroyed by then. The code that i have till now for the same is

    HttpRequest* send(string reply)
    {
            int len = strlen(reply.c_str());
            char *buffer = new char[len+1];
            strncpy(buffer, reply.c_str(), len);
            cout << "LEN:"<<reply.length()<<endl;
            cout << "OG:"<<reply<<endl<<"TC:"<<buffer<<endl<<"CS"<<reply.c_str()<<endl;
            this->res.response = "test";
            return this;
    };

res.response is the char * that i want to store the value in. The output from cout that i am getting is

LEN:5
OG:hello
TC:hello�������������������q{
CShello

This behavior is pretty strange to me. Can someone please explain what i am doing wrong. Also the above code shows me using strlen but i am getting the same result using length() in c++ also.

Also it is worth mentioning that this happens only the first time that i invoke this, after that it goes fine.

Upvotes: 0

Views: 1591

Answers (4)

Vlad from Moscow
Vlad from Moscow

Reputation: 310950

The problem is that this statement

strncpy(buffer, reply.c_str(), len);

does not copy the terminating zero ( '\0' ) of the original string to buffer.

You should use the standard C function strlen with objects of type std::string only in case when the objects contain embedded zeroes. Otherwise use member functions of the class std::string size or length.

Instead of the standard C function strncpy you could use standard C function strcpy to copy the zero-terminated string in the buffer.

For example

    char *buffer = new char[len+1];
    strcpy( buffer, reply.c_str() );

Upvotes: 1

MikeCAT
MikeCAT

Reputation: 75062

Your arguments to strncpy() make the function misunderstand that there is no space for terminating null-character, so it isn't written. Correct the argument like

strncpy(buffer, reply.c_str(), len+1);

In this code, it is guaranteed that the length of buffer is sufficient to store the string, so you can simply use strcpy() instead of the strncpy() like this:

strcpy(buffer, reply.c_str());

You can use strdup() function if your system supports it. Using it, the lines

int len = strlen(reply.c_str());
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);

can be replaced with

char *buffer = strdup(reply.c_str());

Note that strdup() is a function from C and it uses malloc() internally, so you must use free(), not delete[], to free the memory allocated via strdup().

Upvotes: 3

Pete Becker
Pete Becker

Reputation: 76245

Don't use strncpy until you've read and understood its documentation. And then don't use it. It's a very specialized function, and there's no need to deal with its quirks here. The code in the question allocates enough space for the result, so just use strcpy.

Upvotes: 1

kirbyfan64sos
kirbyfan64sos

Reputation: 10727

You never put the null terminator:

char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
buffer[len] = 0; // <-- HERE

strncpy doesn't add it.

Upvotes: 10

Related Questions