curl_easy_perform() API crashes [duplicate] - c++

This question already has an answer here:
libcurl returns CURLcode 23
(1 answer)
Closed 7 months ago.
I am trying to get the idea about libcurl and I am trying to download simple photo from the url. But my program crashes when it goes inside curl_easy_perform() API. Any idea about it?
#include <stdio.h>
#include <curl/curl.h>
#include <QDebug>
#include <string>
int main(void)
{
CURL *curl;
FILE *fp;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
std::string url = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Nusfjord_road%2C_2010_09.jpg/1280px-Nusfjord_road%2C_2010_09.jpg";
//std::string url = "https://ra-jenkins-nyk01.siemens.net/job/TestCase_Logs/ws/OBU_Int_Build/TestCases/TC_30520_OBU_detects_dir_to_increase_whn_conf_increase_dir/TC_30520_OBU_detects_dir_to_increase_whn_conf_increase_dir.ctr";
char outfilename[FILENAME_MAX] = "D:/ankit.jpg";
curl = curl_easy_init();
if (curl)
{
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
//curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
if(res == CURLE_OK)
printf("Download Successful.");
else
printf("Not sucessful");
curl_easy_cleanup(curl);
fclose(fp);
}
return 0;
}
Compiler :- mingw
libcurl version :7.84.0

I wonder if you are using libcurl library as a win32 dll or static library, according to the libcurl official documentation, it says
If you are using libcurl as a win32 DLL, you MUST use a
CURLOPT_WRITEFUNCTION if you set this option or you will experience
crashes.
You may want to see in here: click

Related

libcurl - "curl_easy_cleanup()" is causing malloc error (C++)

When running my code (pertinent sections pasted below), I periodically get the following error:
program(34010,0x70000e58b000) malloc: *** error for object
0x7fc43d93fcf0: pointer being freed was not allocated set a breakpoint
in malloc_error_break to debug Signal: SIGABRT (signal SIGABRT)
I am running multi-threaded C++ code on a Macbook (OS-10.13) wherein different threads make use of the code in question simultaneously. To my knowledge, libcurl is indeed thread safe as long as I do not utilize the same "curl handle" (which I understand to be an instance of "CURL" aka "CURL *curl = curl_easy_init();") in two different threads at the same time. In my case, since each thread calls the function separately and initializes a new instance of a CURL object, I should be "safe", right? Hopefully there is something obvious that I'm missing that is causing me (or lib curl in this case) to attempt to free memory that has already been freed. If there is any more information I should have included (below) please don't hesitate to let me know.
The function that seg faults is
string http_lib::make_get_request(string url)
on the line that reads
curl_easy_cleanup(curl);
and sometimes (less often) on the line that reads
res = curl_easy_perform(curl);
Below is what I think would be the pertinent sections of my code:
size_t http_lib::CurlWrite_CallbackFunc_StdString(void *contents, size_t size, size_t nmemb, std::string *s)
{
size_t newLength = size*nmemb;
size_t oldLength = s->size();
try
{
s->resize(oldLength + newLength);
}
catch(std::bad_alloc &e)
{
//handle memory problem
return 0;
}
std::copy((char*)contents,(char*)contents+newLength,s->begin()+oldLength);
return size*nmemb;
}
string http_lib::make_post_request(string url, vector<string> headers, string post_params) {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
string s;
if(curl)
{
struct curl_slist *chunk = NULL;
for(int i=0; i<headers.size(); i++){
/* Add a custom header */
chunk = curl_slist_append(chunk, headers[i].c_str());
}
/* set our custom set of headers */
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_params.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //only for https
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //only for https
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
if(networking_debug){
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //verbose output
}
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
/* always cleanup */
curl_easy_cleanup(curl);
}
// Debug output
if (networking_debug){
cout<<"Response: " << s <<endl;
}
return s;
}
string http_lib::make_get_request(string url) {
//SslCurlWrapper sslObject;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
string s;
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
//tell libcurl to follow redirection
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //only for https
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //only for https
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
if(networking_debug){
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //verbose output
}
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
if (networking_debug){
cout << "Response: " << s << endl;
}
return s;
}
In main() I have
int main(int argc, char *argv[]){
// Initialize http_lib (curl)
curl_global_init(CURL_GLOBAL_DEFAULT);
... spin up 10 or so threads that make get/post requests to https site (some requests utilize the make_post_request() function and others utilize make_get_requet() function).
}
CMAKE doesn't/didn't seem to want to use anything other than CURL_ROOT_DIR of "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include" for libcurl (aka curl).
Thus it was using the curl lib that mac (and/or Xcode) ships with. I haven't figured out what version that is, but I can say that not using it and instead using CURL version 7.57 is what fixed my issue.
I used "brew" package manager to
brew install curl
Doing so created /usr/local/Cellar/curl/7.57.0 directory and put all libs/includes in there.
Then I added
-I/usr/local/Cellar/curl/7.57.0/include -L/usr/local/Cellar/curl/7.57.0/lib
to my CMAKE CMAKE_CXX_FLAGS.
TLDR; Solution was to ensure I was using the newest version of the curl lib. Now that I am, no problem.

Using CURL in function in c++

I'm trying tu use curl in c++ using function.
Example:
#define ...
...
...
/* CURL parameters */
CURL *curl = curl_easy_init();
CURLcode res;
string readBuffer;
void setHeader(){
if(curl) {
/* Headers */
struct curl_slist *chunk = NULL;
chunk = NULL;
chunk = curl_slist_append(chunk, "Connection:keep-alive");
..
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
}
}
void myFunction1(){
setHeader();
curl_easy_setopt(curl, CURLOPT_URL, "....");
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookiePath);
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookiePath);
res = curl_easy_perform(curl);
cout << readBuffer;
curl_easy_cleanup(curl);
}
void myFunction2(){
setHeader();
curl_easy_setopt(curl, CURLOPT_URL, "....");
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookiePath);
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookiePath);
res = curl_easy_perform(curl);
cout << readBuffer;
curl_easy_cleanup(curl);
}
In the main function i call myFunction1 or myFunction2;
I don't know if is right to use libcurl in this way, but I'm having a problem.
I use this to login in my site, so I save the cookie whit this code:
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookiePath);
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookiePath);
int main(){
curl_global_init(CURL_GLOBAL_ALL);
myFunction1();
myFunction2();
curl_global_cleanup();
}
Suppose i login and save the cookie in myFunction1.
When I'm trying to set in the myFunction2 it crash on the CURLOPT_COOKIEFILE row.
I don't know why the cookie is saved in the file, but it can't be used beacuse when I run the program it crash on that row.
Sorry for my English
Thank's
The reason of my problem is that when I use the curl_easy_cleanup(curl) and then curl_easy_init I change the sessionID, so the cookie that I've saved are no longer good. So I use at the first curl_easy_init, then I make all my request in my functions, and at the end of my program I use curl_easy_cleanup. To clean the CURL OPTION you can use: curl_easy_reset(). I've update this post for people that can have my same problem.

How to use libcurl in c++ to send POST to elasticsearch

does anyone knows the exact syntax for using elasticsearch with libcurl?
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:9200/bro-201409170900/http/ZinAvJ-ETT-mycy2jyRkdg/_update -d");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"script\" : \"ctx._source.longitude += 3\"}");
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 1;
}
This code does ont update the longitude parameter and I don't know why.
One should not specify the "-d' in the url. The command line tool is just build on top of libcurl.
If you want to see what the c code for the post request would look like you could use the libcurl option with command line .
example :
curl localhost:9200/bro-201409170900/http/ZinAvJ-ETT-mycy2jyRkdg/… -d '{ "script" : "ctx._source.longitude += 2"}' --libcurl output.c
A simple "C" implementation would look something on these lines
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
char *postFields = "{\"script\" : \"ctx._source.longitude += 3\"}";
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:9200/bro-201409170900/http/ZinAvJ-ETT-mycy2jyRkdg/_update");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl,CURLOPT_POSTFIELDS,postFields);
curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,strlen(postFields));
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return res;
}

CURLE_COULDNT_CONNECT - while Internet is ok and server is available

I get this error from Curl, yet, the site is available, and I see nothing going out on wireshark.
What might cause this error ?
I've try to run it against www.google.com and got the same error.
this very code was working a few hours ago. I have no idea what might cause this.
here is the code:
CURL *curl;
CURLcode res = CURLE_OK;
struct curl_slist *headers=NULL;
headers = curl_slist_append(headers, "Content-Type: text/xml");
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
struct rcvdstring s;
init_string(&s);
string FullAddress = URL+Method;
curl_easy_setopt(curl, CURLOPT_URL, FullAddress.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, DATA.c_str());
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
char buf[1024];
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
res = curl_easy_perform(curl);
Respons.assign(s.ptr);
return res;
}
* Update - took the exe to another computer, it works there. This is local to my computer....
Ok, Moving the code to another computer - showed me the code is OK.
The problem was with Norton Internet Security that after a few days of developing decided to block my communication DLL.

What's the proper way of using libcURL without the dlls?

recently managed to use a libcurl in a test program for downloading a files.
The code is this:
CURL * curl;
FILE * fout;
CURLcode result;
char * url = "http://blablabla.com/blablabla.txt";
char filename[FILENAME_MAX] = "blablabla.txt";
curl = curl_easy_init();
if (curl)
{
fout = fopen(filename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fout);
result = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fout);
}
and those things for directives:
#define CURL_STATICLIB
#include <curl/curl.h>
My question is how to make that I don't need to copy all of its dlls in the same dir with the exec to make it work:
libcurl.dll
libeay32.dll
libidn-11.dll
librtmp.dll
libssh2.dll
libssl32.dll
zlib1.dll
Cannot find info about that in the homesite (http://curl.haxx.se) of the library :|
You mean, "how do I statically link libcurl"?
5.7 in the FAQ says:
When building an application that uses the static libcurl library, you must add -DCURL_STATICLIB to your CFLAGS. Otherwise the linker will look for dynamic import symbols. If you're using Visual Studio, you need to instead add CURL_STATICLIB in the "Preprocessor Definitions" section.
CURL *curl;
CURLcode res;
CString strUser;
FILE *ftplister;
m_FTPUserName.GetWindowTextW (strUser);
CT2CA PUF_File_HostName(PUF_FIle_Host);
CT2CA FTP_UserName(FTP_USERNAME);
FTP_PASSWORD.Append(L":");
FTP_PASSWORD.Append(FTP_USERNAME);
CT2CA FTP_Password(FTP_PASSWORD);
CT2CA FTP_AddressName(FTP_Address);
CString strLocalFile;
CString strFileName;
m_FTPFileName.GetWindowTextW(strFileName);
strLocalFile.Append(FTP_FileName);
strLocalFile.Append(L"\\");
strLocalFile.Append(strFileName);
CT2CA PUF_LocalFile(strLocalFile);
//ofstream stream2(PUF_LocalFile);
curl = curl_easy_init();
if(curl)
{
ftplister=fopen(PUF_LocalFile,"wb");
curl_easy_setopt(curl,CURLOPT_URL,PUF_File_HostName);
if(strUser!=_T(""))
{
curl_easy_setopt(curl,CURLOPT_USERPWD,FTP_Password);
}
curl_easy_setopt(curl, CURLOPT_FTP_SSL, TRUE);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, ftplister);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(ftplister);
}