Variable sized char[] - Is it OK?
forgive me if this is stupid but I'm newer to C/C++.
In the socket library I'm creating, my ClientSocket::recv(int bufsize) function uses 'bufsize' to initialize a char[] array to read into from the C socket. The code, given you compile with G++, works fine.
The issue I am having is that some people that are compiling my code are getting the following error: socket.cxx||In member function ‘std::string ClientSocket::recv(int)’:|
socket.cxx|269|error: ISO C++ forbids variable length array ‘buffer’|
Now, from what I've read on this forum is that Microsoft only supports C89, whereas GCC supports C99 in which variable-sized arrays are acceptable. Also on that thread, they suggested using _alloca() - The problem is, that supports only up to 1mb. I'd rather there not be a limit.
If that is the only possible way to make it cross-compilable with GCC/MSVC++, I guess I'll have to live with it. It'd be nice to know a alternative though. Would something like malloc() work? (never used it before, so I don't know) If so, could you please tell me how to use it or link to a tutorial/docs? Thanks!
P.S.: Here's the code for my recv() function:
std::string ClientSocket::recv(int bufsize) {
// isConnected() is a ClientSocket function
if (!isConnected()) throw SocketException("Not connected.");
char buffer[bufsize+1];
// I did this because sometimes it was returning partial garbage :\
memset(buffer, 0, bufsize);
// the :: prefix means to call the recv() from the header files instead of ClientSocket::recv()
int ret = ::recv(sockfd, buffer, bufsize-1, 0);
if (ret < 0) {
switch(errno) {
case ECONNREFUSED:
throw SocketException("Connection refused on recover.");
break;
case ENOTCONN:
throw SocketE开发者_JAVA技巧xception("Not connected.");
break;
default:
throw SocketException("Unknown error reading socket.");
break;
}
} else if (ret == 0) {
// we got disconnected, return empty string. (connected is a protected variable of ClientSocket)
connected = false;
return "";
}
return buffer;
}
EDIT: As per recommendations, I plan to use either vector buffer(bufsize+1, 0); ... recv(sockfd, &buffer[0], bufsize, 0); ... return &buffer[0];
OR char *buffer = new char[bufsize + 1]; memset(buffer, 0, bufsize); ... recv(sockfd, buffer, bufsize, 0); ... string tmp = buffer; delete [] buffer; return string(tmp);
- Still installing MSVC++ in order to test it, but I believe it will work. THANK YOU SO MUCH! StackOverflow ROCKS!
g++ allows C99 Variable Length Arrays in C++ as a language extension.
they're not supported by standard C++.
in C++ use a std::vector
or std::string
.
Cheers & hth.,
Try doing this:
char * buffer = new char[bufsize + 1];
I would create a simple buffer class that wrapped a char *
to deal with this. It would use new
to allocate the buffer. I believe it is also possible to use a vector
and still be standards compliant. But I'm not completely sure how to go about it in the recommended way.
you don't even need to use memset, if you're on gcc or g++ you can actually assign it all zeros using normal aggregation on the char type, consider this:
char * buffer[bufsize+1] = {0};
this code will work in gcc/g++ only because gcc allows variable sized arrays on the stack.
Your only other option is to use:
char * buffer = new char[bufsize+1];
// and assign it zeros with std::fill
std::fill(buffer, buffer+bufsize+1, 0);
精彩评论