strcat() Problems

  • Thread starter Patrick Coleman
  • Start date
P

Patrick Coleman

Hi,
I have the following code:

char request[] = "GET ";
strcat(request, path); //Path is the path section of a url ie. "/path/test.htm"
strcat(request, " HTTP/1.1");

cout<<request<<"\n"; //This outputs "GET /path/test.htm HTTP/1.1" happily

//Send packet (I know there's no error checking, this is just an example)
int numbytes;
numbytes = send(socknum, request, sizeof(request), 0));

cout<<"Tried to send "<<sizeof(request)<<" bytes, sent "<<numbytes<<" bytes.\n";
//This line outputs 5 bytes Tried, 5 bytes sent, which is my problem

The problem with this is that when I check the packet sent (with a packet
sniffer) the packets only contains "GET " (It should contain
"GET /path/test.htm HTTP/1.1"). It seems to me that only the variable
declaration is storing the data properly, and the strcat command just
'links' that data somehow...(I'm probably wrong, but thats my (vague) idea of the
situation, anyway)

How can I get around this? I know if I declare request of a fixed length,
ie.
char request[1024] = "GET ";
strcat(request, path);
strcat(request, " HTTP/1.1");

It outputs everything, but request is padded with \0 which confuses the
other server even more. Besides, if the path is longer than that, it'll
screw up...

Thanks for any help in advance,
Patrick
 
A

Alf P. Steinbach

I have the following code:

char request[] = "GET ";

Use a std::string, because

strcat(request, path); //Path is the path section of a url ie. "/path/test.htm"

otherwise you're likely to write to arbitrary parts of memory, willy-nilly,
like you do here

strcat(request, " HTTP/1.1");

and here.

cout<<request<<"\n"; //This outputs "GET /path/test.htm HTTP/1.1" happily

This may or may not "work" depending on the weather situation in Australia.


//Send packet (I know there's no error checking, this is just an example)
int numbytes;
numbytes = send(socknum, request, sizeof(request), 0));

Use std::string, because otherwise you're likely to use the wrong operators
and functions, as you do here.
 
P

Patrick Coleman

Use std::string, because otherwise you're likely to use the wrong operators
and functions, as you do here.

I have tried using an std::string, with the same results.
-Patrick
 
C

Christopher

Patrick Coleman said:
I have tried using an std::string, with the same results.
-Patrick

You can't use char variable[] like it will magically grow and allocate
memory by itself. The fact that you said, "besides if the path is longer
than that, it'll screw up" implies that you need a better data structure,
one that allocates and releases it's memory by itself. As was said,
std::string is perfect for the job. If you really gave it a try and got the
same results I don't think you could have been using the string properly.
Post the code using std::string and maybe we can help you find where the
problem is with it. Other than using std::string you will have to make a
static array big enough to handle any case. Dealing with the null character
at the end could be done by not sending that byte. I don't know if yer using
tcp or udp, and both are really not on topic for this newsgroup, but if you
are using tcp than consider putting a loop around your send function
getting,checking, and sending each byte from the buffer and exiting on a
NULL character instead of sending it.
,
Christopher
 
F

Frank Xie

Patrick Coleman said:
I have tried using an std::string, with the same results.
-Patrick

char *strcat(char *dest, const char *src) requires dest string must
have enough space for the result (for both dest and src)
 
J

John Harrison

Patrick Coleman said:
I have tried using an std::string, with the same results.
-Patrick

Try using std::string *properly* then. You make two big mistakes, not
allocating memory and misunderstand sizeof. std::string provides safe
alternatives for both.

std::string request = "GET ";
request += path;
request += " HTTP/1.1";

cout<<request<<"\n"; //This outputs "GET /path/test.htm HTTP/1.1" happily

int numbytes;
numbytes = send(socknum, request.data(), request.size(), 0));

+= instead of strcat, request.size() instead of sizeof(request),
request.data() to get the char pointer.

john
 
P

Patrick Coleman

Thanks for all the info. I wasnt using std::string properly (as you
guessed :) - the example clarified things for me. I was doing:

request = request + path;

Which is obviously a flashback from my VB days :/
Thanks again for the info,
Patrick
 
K

Karl Heinz Buchegger

Patrick said:
Thanks for all the info. I wasnt using std::string properly (as you
guessed :) - the example clarified things for me. I was doing:

request = request + path;

Which is obviously a flashback from my VB days :/

Nothing wrong with the above.
Your problem must have been something else
 
S

Stephen Howe

Hi,
I have the following code:

char request[] = "GET ";

request is a buffer of exactly 5 characters :- 'G', 'E', 'T', ' ', '\0'
There is _NO_ space for any more characters
strcat(request, path); //Path is the path section of a url ie.
"/path/test.htm"

ILLEGAL !!! - you are overwriting beyond the end of request[]. request[]
won't grow in size. You can only do strcat() if you have pre-allocated
enough space to write the characters in.
strcat(request, " HTTP/1.1");

ILLEGAL !!! - you are overwriting beyond the end of request[], again.
cout<<request<<"\n"; //This outputs "GET /path/test.htm HTTP/1.1" happily

It may well do. You have got away with it. But have no doubt, the above
strcat's caused problems. Now if you originally said

char request[256] = "GET "; // note the number 256

providing your total buffer size was less than 256 characters (including the
terminating '\0'), your strcat's would work.
cout<<"Tried to send "<<sizeof(request)<<" bytes, sent "<<numbytes<<" bytes.\n";
//This line outputs 5 bytes Tried, 5 bytes sent, which is my problem

Because sizeof() is the wrong thing. If you

char request[256] = "GET "; // note the number 256

you don't want to output 256 (what sizeof would return) do you when only
send, sy 40 characters? It should be

cout<<"Tried to send "<<strlen(request)<<" bytes, sent "<<numbytes<<"
bytes.\n";
How can I get around this? I know if I declare request of a fixed length,
ie.
char request[1024] = "GET ";
strcat(request, path);
strcat(request, " HTTP/1.1");

Which is correct. You provide enough space.
It outputs everything, but request is padded with \0 which confuses the
other server even more. Besides, if the path is longer than that, it'll
screw up...

These use strlen() not sizeof(). You are only using part of the buffer, not
all of it. sizeof returns the total size of the buffer.

Stephen Howe
 
L

llewelly

Patrick Coleman said:
Thanks for all the info. I wasnt using std::string properly (as you
guessed :) - the example clarified things for me. I was doing:

request = request + path;
Which is obviously a flashback from my VB days :/
[snip]

?
I'm confused. This:

int main()
{
std::string request;
std::string path;
request= request + path;
}

is a perfectly valid use of string in C++.
More, in VB, IIRC, one concatenates strings with '&', not '+'.
 
P

Patrick Coleman

Patrick Coleman said:
Thanks for all the info. I wasnt using std::string properly (as you
guessed :) - the example clarified things for me. I was doing:

request = request + path;
Which is obviously a flashback from my VB days :/
[snip]

?
I'm confused. This:

int main()
{
std::string request;
std::string path;
request= request + path;
}

is a perfectly valid use of string in C++.
More, in VB, IIRC, one concatenates strings with '&', not '+'.

Hmm. When I used the code request = request + path;, I'm pretty sure that
I got the same problem that I started out with, that it would only send
"GET ". This is what I used:

request = "GET " + path + " HTTP/1.1";
Is that valid?
 
K

Karl Heinz Buchegger

Patrick said:
Patrick Coleman said:
Thanks for all the info. I wasnt using std::string properly (as you
guessed :) - the example clarified things for me. I was doing:

request = request + path;
Which is obviously a flashback from my VB days :/
[snip]

?
I'm confused. This:

int main()
{
std::string request;
std::string path;
request= request + path;
}

is a perfectly valid use of string in C++.
More, in VB, IIRC, one concatenates strings with '&', not '+'.

Hmm. When I used the code request = request + path;, I'm pretty sure that
I got the same problem that I started out with, that it would only send
"GET ". This is what I used:

request = "GET " + path + " HTTP/1.1";
Is that valid?

Yep.
Your problem might have been when you actually sent the string.
If I remember correctly the code snippet you posted used 'sizeof'
to determine the string length, which of course is nonsense.
sizeof is evaluated at compile time, so how can it detect the
length of something growing and shrinking during runtime?
 
L

llewelly

Patrick Coleman said:
Patrick Coleman said:
Thanks for all the info. I wasnt using std::string properly (as you
guessed :) - the example clarified things for me. I was doing:

request = request + path;
Which is obviously a flashback from my VB days :/
[snip]

?
I'm confused. This:

int main()
{
std::string request;
std::string path;
request= request + path;
}

is a perfectly valid use of string in C++.
More, in VB, IIRC, one concatenates strings with '&', not '+'.

Hmm. When I used the code request = request + path;, I'm pretty sure that
I got the same problem that I started out with, that it would only send
"GET ". This is what I used:

request = "GET " + path + " HTTP/1.1";
Is that valid?

Let's try that again. I wrote:

#include<string>
#include<iostream>
#include<ostream>

int main()
{
std::string request;
std::string path= "/home/llewelly/cc_moderated/adl.cc";
char const* path2= "/home/llewelly/cc_moderated/adl.cc";
request = "GET " + path + " HTTP/1.1";
//request = "GET " + path2 + " HTTP/1.1"; //Compile-time error.
std::cout << request << std::endl;
}

and when I ran it, I got:

GET /home/llewelly/cc_moderated/adl.cc HTTP/1.1

If I uncomment the line using path2 (which is a char const*, *not* a
std::string), I get:

str4.cc: In function `int main()':
str4.cc:9: error: invalid operands of types `const char[5]' and
`const char*' to binary `operator+'


as a compile time error.

Does that help?

When you concatenate strings using +, one of the two strings must be
an std::string. When you chain several concatenations together,
one of the first two must be an std::string .
 
R

Ron Natalie

llewelly said:
request = "GET " + path + " HTTP/1.1";
//request = "GET " + path2 + " HTTP/1.1"; //Compile-time error.

The + operator can't be overloaded on pointers alone. One operand must be
of type string (and so will the result0. The second would have worked if you
had done:
request = "GET" + string(path2) + " HTTP/1.1";
Forces the middle value to string type.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top