-3

I am curious why Alternative #1 functions okay while Alternative #2 returns CURLE_OPT_MALFORMAT when I do a curl_easy_perform(m_curl);

Alternative #1

curl_easy_reset(m_curl);
char sUrl[8192];
/* In Alternative #1, m_strUrl is a C++ std::wstring member variable */
wcstombs(sUrl, m_sUrl.c_str(), m_sUrl.length());
sUrl[m_sUrl.length()] = '\0';
CURLcode code = curl_easy_setopt(m_curl, CURLOPT_URL, sUrl);
CURLcode perform = curl_easy_perform(m_curl);

Alternative #2

curl_global_init(CURL_GLOBAL_ALL);
 /* init the curl session */
 m_curl_handle = curl_easy_init();
/* set URL to get here*/
/* In Alternative #2, m_strUrl is a C++ std::string member variable */
 CURLcode retval = curl_easy_setopt(m_curl_handle, CURLOPT_URL, (char
*)m_sUrl.c_str());
CURLcode perform = curl_easy_perform(m_curl);

I read the following URL

How to convert a std::string to const char* or char*?

If you just want to pass a std::string to a function that needs const char* you can use

std::string str;
const char * c = str.c_str();

If you want to get a writable copy, like char *, you can do that with this:

std::string str;
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0'; // don't forget the terminating 0
// don't forget to free the string after finished using it
delete[] writable;

Edit: Notice that the above is not exception safe. If anything between the new call and the delete call throws, you will leak memory, as nothing will call delete for you automatically. There are two immediate ways to solve this.

I am wondering why Alternative #2 chokes when I do:

 CURLcode retval = curl_easy_setopt(m_curl_handle, CURLOPT_URL, (char*)m_sUrl.c_str());

Is it necessary that I create a writable copy , like (char*) with

std::string str;
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0'; // don't forget the terminating 0

When I use in a Windows thread function: curl_easy_setopt(m_curl_handle, CURLOPT_URL, (char*)m_sUrl.c_str()); followed by: CURLcode retval = curl_easy_perform(m_curl);

the Windows thread function terminates early after: CURLcode retval = curl_easy_perform(m_curl) so that I can't read the CURLcode associated with curl_easy_perform(m_curl).

Any help is greatly appreciated

Community
  • 1
  • 1
Frank
  • 1,406
  • 2
  • 16
  • 42
  • 76 questions asked and you still don't know how to properly format them? – Praetorian Jul 31 '15 at 06:33
  • @Praetorian,Thank you for properly formatting my question. Could you please comment on my question? Thank you very much. – Frank Jul 31 '15 at 07:58
  • You can use `std::vector writable(size);` instead of `char *writable = new char[size];`. That should be exception safe. – rodrigo Jul 31 '15 at 08:20
  • @rodrigo, Thank you for your comment. I have a question for you. First, how do we transfor, a std::vector to a char* pointer required by CURLcode code = curl_easy_setopt(m_curl, CURLOPT_URL, sUrl); Thank you very much. – Frank Jul 31 '15 at 08:52
  • @Frank: Easy, use the `writable.data()` member function. It returns a `char *`. Alternatively you can use `&writable[0]` because the memory of a vector is contiguous. – rodrigo Jul 31 '15 at 08:56
  • @rodrigo, Please read http://stackoverflow.com/questions/13160290/curl-easy-perform-crashes-when-the-url-is-not-correct – Frank Jul 31 '15 at 09:03
  • @rodrigo, Thank you for your comment. I have two questions for you. Why does Alternative # 1 cause the Windows thread function to exit early? Is it related to: http://stackoverflow.com/questions/13160290/curl-easy-perform-crashes-when-the-url-is-not-correct . Second , should it read std::copy(str.begin(), str.end(), writable.begin()); Thank you very much. – Frank Jul 31 '15 at 09:07
  • @rodrigo, Thank you for your comment, If writable is a std::vector should the line be : writable[str.size()] = '\0'; // don't forget the terminating 0 or will that cause a buffer overrun. Thank you very much. – Frank Jul 31 '15 at 09:18
  • @Frank: Yes and yes. But I like better: `strcpy(writable.data(), str.c_str());`. That will add the terminating NUL character automatically. If you are handling raw C string use proper raw C string functions. – rodrigo Jul 31 '15 at 09:34
  • @Frank: About why fails, I don't know. But it should be `size_t nb = wcstombs(...); sUrl[nb] = '\0'`. – rodrigo Jul 31 '15 at 09:36
  • @rodrigo, How does curl_easy_perform function when a timeout threshold is exceeded? Thank you very much. – Frank Aug 01 '15 at 04:06

2 Answers2

0

I just tested this C++ code on an AXIS P1347 Network Camera and it functions properly.

std::vector<char> writable(m_sUrl.size());

strcpy(&writable[0], m_sUrl.c_str()); 

CURLcode retval = curl_easy_setopt(m_curl_handle, CURLOPT_URL, &writable[0]);

CURLcode perform = curl_easy_perform(m_curl_handle);
Martin
  • 3,960
  • 7
  • 43
  • 43
Frank
  • 1,406
  • 2
  • 16
  • 42
0

Null termination of URL arguments passed to curl_easy_setopt with the option CURLOPT_URL is important. Equally important is to recognize that if the URL parses correctly in the libcurl static function parseurandfillconn(..), curl_easy_perform blocks until the requested transfer callbacks are completed or timeout. Please refer to the uRL Is curl_easy_perform() synchronous or asynchronous? for details. If there is malformated URL detected by the libcurl static function parseurandfillconn(..), curl_easy_perform returns immediately without blocking.

Community
  • 1
  • 1
Frank
  • 1,406
  • 2
  • 16
  • 42