first I woud like to say that I saw similar post , and I posted this one on it but was removed... so all is in the title. I understood that it could be a problem at the linker step but I don't know why. Indeed, I linked all the (*.a) files on my Code::Blocks projet and added the different paths of the curl library in Linker options and search directories.
I also tried to manually compil and link but I did not succeed.
g++ -L ..\lib\curl\lib64 -I ..\lib\curl\include -lcurl main.cpp
Another attempt
g++ main.cpp -L ..\lib\curl\lib64 -I ..\lib\curl\include -lcurl -o test.exe
This is the error : " undefined reference to 'curl_easy_init' "
This is my code , maybe the source of troubles is here but I don't think so (tried the static lib too )
#include <iostream>
#define CURL_STATICLIB
#include <curl/curl.h>
#include <curl/easy.h>
#include <string>
#include <fstream>
#include <unistd.h>
#include <windows.h>
#include <Lmcons.h>
using namespace std;
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t written = fwrite(ptr, size, nmemb, stream);
return written;}
int main(void)
{
/*ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();*/
CURL *curl;
FILE *fp;
CURLcode res;
char *url = "http://stackoverflow.com";
char outfilename[FILENAME_MAX] = "page.html";
curl = curl_easy_init();
if (curl) {
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
fclose(fp);
}
return 0;
}
#pragma once
#ifndef __CURL_CURL_H
#include "curl.h"
#endif
#ifndef __CURL_EASY_H
#include "easy.h"
#endif
#include <stdint.h>
#include <memory>
#include <string>
namespace CommUnit
{
enum ERR_PROXY
{
ERR_CURL_INIT_FAILED = 0xA0,
ERR_SET_PROXY_FAILED = 0xA1,
};
class MyProxy
{
public:
static MyProxy & GetInstance() //Meyers' Singlton
{
static MyProxy ProxySigleton;
return ProxySigleton;
}
public:
/*
* #bref:Get request
* #param[in] sUrl:Access URL
* #param[in] sProxyIp:Proxy IP
* #param[in] uProxyPort:Proxy Port
* #param[in] uTimeOut:Time out
* #param[in] isSSL:HTTPS true,else false
* #param[out] sRetContent:Return the URL content
*/
uint32_t Get(const std::string &sUrl,
const std::string& sProxyIp,
uint32_t uProxyPort,
uint32_t uTimeOut,
bool isSSL,
std::string &sRetContent);
private:
MyProxy(); //Constructor hidden
MyProxy(MyProxy const &); //Copy-Constructor hidden
MyProxy & operator= (MyProxy const &); //Assign operator hidden
~MyProxy(); //Destructor hidden
inline void _setCurlopt(CURL *pCurl,
const std::string &sUrl,
std::string &sWriterData,
const uint32_t uTimeOut,
bool isSSL);
//Callback function, write data to writerData
static int Writer(char *data,
uint32_t size,
uint32_t nmemb,
std::string *writerData);
private:
std::string m_sErrMsg;
static char s_ErrBuffer[CURL_ERROR_SIZE];
static const uint32_t m_MAXBUF = 2 * 1024 * 1024 - 128;
};
}
//////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <string>
#include "MyProxy.h"
#include "Log.h"
#include <curl.h>
using namespace CommUnit;
char MyProxy::s_ErrBuffer[CURL_ERROR_SIZE] = { 0 };
MyProxy::MyProxy(void)
{
CURLcode oCURLcode = curl_global_init(CURL_GLOBAL_ALL);
if (oCURLcode != CURLE_OK)
{
Log("ERR: %s curl_init failed!", __func__);
}
}
MyProxy::~MyProxy(void)
{
curl_global_cleanup();
}
uint32_t MyProxy::Get(const std::string &sUrl,
const std::string& sProxyIp,
uint32_t uProxyPort,
uint32_t uTimeOut,
bool isSSL,
std::string &sRetContent)
{
sRetContent.clear();
CURL *pCurl = curl_easy_init();
CURLcode oCURLcode;
if (nullptr == pCurl)
{
Log("ERR: %s curl_easy_init failed!", __func__);
return ERR_CURL_INIT_FAILED;
}
_setCurlopt(pCurl, sUrl, sRetContent, uTimeOut, isSSL);
if (0 == sProxyIp.length()|| 0 == uProxyPort)
{
Log("ERR: %s SetProxy: ProxyIp [%s], ProxyPort[%u] failed",__func__, sProxyIp.c_str(), uProxyPort);
return ERR_SET_PROXY_FAILED;
}
Log("INFO: %s SetProxy: ProxyIp [%s], ProxyPort[%u] failed", __func__, sProxyIp.c_str(), uProxyPort);
curl_easy_setopt(pCurl, CURLOPT_PROXY, sProxyIp.c_str());
curl_easy_setopt(pCurl, CURLOPT_PROXYPORT, uProxyPort);
int iTimes = 0;
while (true)
{
oCURLcode = curl_easy_perform(pCurl);
if (oCURLcode != CURLE_OK && ++iTimes < 3)
usleep(5);
else
break;
}
if (oCURLcode != CURLE_OK)
{
Log("ERR: %s curl_easy_perform failed!", __func__);
}
curl_easy_cleanup(pCurl);
return oCURLcode;
}
void MyProxy::_setCurlopt(CURL *pCurl,
const std::string &sUrl,
std::string &sWriterData,
const uint32_t uTimeOut,
bool isSSL)
{
curl_easy_setopt(pCurl, CURLOPT_ERRORBUFFER, s_ErrBuffer);
curl_easy_setopt(pCurl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(pCurl, CURLOPT_URL, sUrl.c_str());
curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, uTimeOut);
Log("INFO: %s Set Url:[%s],TimeOut:[%d]", __func__, sUrl.c_str(), uTimeOut);
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, MyProxy::Writer);
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &sWriterData);
//Skip peer and hostname verification
if (isSSL)
{
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
}
}
int MyProxy::Writer(char *data,
uint32_t size,
uint32_t nmemb,
std::string *writerData)
{
if (writerData == nullptr)
{
Log("ERR: %s writerData is null!", __func__);
return 0;
}
int len = size * nmemb;
if ((writerData->size() + len) > m_MAXBUF)
{
Log("ERR: %s writerData size over MAXBUF!", __func__);
return 0;
}
writerData->append(data, len);
return len;
}
I want to realize a proxy with libcurl, which can get the content of given url(https). Morever, it need to be thread-safety.
But when I created 200 threads with pthreads to test my code, an segment fault occured sometimes.
How can I solve this problem?
Is there a relation with the sRetContent(std::string)?
Thanks!
Errmsg:
double free or corruption (!prev): 0x0ac72840 ***
Segmentation fault
My understanding is that libcurl is not thread-safe if you are using https (and it looks like you are) due to the fact that it is using underlying ssl libraries. See libcurl documentation and OpenSSL documentation for more info.
If your libcurl was compiled with OpenSSL for example then you have to initialize a few callback functions or you could run into issues. This is the sort of thing you need to do (compiles on Windows):
#include <curl/curl.h>
#include <openssl/crypto.h>
void win32_locking_callback(int mode, int type, const char *file, int line)
{
if (mode & CRYPTO_LOCK)
{
WaitForSingleObject(lock_cs[type],INFINITE);
}
else
{
ReleaseMutex(lock_cs[type]);
}
}
void thread_setup(void)
{
int i;
lock_cs=(HANDLE*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
for (i=0; i<CRYPTO_num_locks(); i++)
{
lock_cs[i]=CreateMutex(NULL,FALSE,NULL);
}
CRYPTO_set_locking_callback((void (*)(int,int,const char *,int))win32_locking_callback);
}
void thread_cleanup(void)
{
int i;
CRYPTO_set_locking_callback(NULL);
for (i=0; i<CRYPTO_num_locks(); i++)
CloseHandle(lock_cs[i]);
OPENSSL_free(lock_cs);
}
I always call thread_setup() after my call to curl_global_init(CURL_GLOBAL_ALL)
and then thread_cleanup() right before my call to curl_global_cleanup().
I use this sort of code with libcurl often in load test scenarios and have never run into any issues. If you continue to run into problems, it is not libcurl, but something not being done properly in your code.
libcurl is thread-safe as long as you play by the rules
**How to make a dll using libcurl. can you share me a sample code.**
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <curl/curl.h>
using namespace std; string data; typedef
#ifdef BUILDING_TESTCURL_DLL
#define TESTCURL_DLL __declspec(dllexport)
#else
#define TESTCURL_DLL __declspec(dllimport)
#endif
curl_global_init(CURL_GLOBAL_ALL); //pretty obvious
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, lpURL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_perform(curl);
if (data == "1")
{
//printf("Successfull");
strcpy(Result, "1");
}
v5 = 1;
curl_easy_cleanup(curl);
curl_global_cleanup();
size_t TESTCURL_DLL writeCallback(char* buf, size_t size, size_t
nmemb, void* up) {
for (int c = 0; c<size*nmemb; c++) { data.push_back(buf[c]);
//printf("", buf[c]); } return size*nmemb; //tell curl how many
bytes we handled }
I run this code with MinGW: g++ -shared -o testcurl.dll testcurl.o -Wl,--out-implib,libcurldll.a
it shows error: undefined reference to '_imp_curl_easy_setopt' undefined reference to '_imp_curl_easy_perform' undefined reference to '_imp_curl_easy_init'
Please help me for developing a dll file using curl.
I am using libcurl to download serialized code and bust it open but, I get an error that looks like fstream is missing but it is very much included. I looked around but very little on the error.
Below is the error and code.
What did miss?
compile error output
g++ -g testGetprice2.cpp -o testGetprice2.o -std=gnu++11 -lcurl
testGetprice2.cpp: In function 'int getData()':
testGetprice2.cpp:45:56: error: 'ios_base' has not been declared
testGetprice2.cpp:45:72: error: 'ios_base' has not been declared
code:
#include "rapidjson/include/rapidjson/document.h"
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <curl/curl.h>
#include <unistd.h>
#include <unordered_map>
#include <string>
using namespace rapidjson;
struct myData
{
std::fstream *file;
std::string *str;
};
size_t write_data(void *ptr, size_t size, size_t nmemb, myData *data)
{
size_t numBytes = size * nmemb;
if (data->file)
data->file->write((char*)ptr, numBytes);
if (data->str)
*data->str += std::string((char*)ptr, numBytes);
return numBytes;
}
//function to get coin data and perform analysis
int getData()
{
int count = 0;
//begin non terminating loop
while(true)
{
count++;
CURL *curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, "http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=155");
std::fstream file("/home/coinz/cryptsy/myfile.txt", ios_base::out | ios_base::ate);
std::string json;
myData data;
data.file = &file;
data.str = &json;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
/* Perform the request, res will get the return code */
CURLcode res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
{
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
}
else
{
file << std::endl;
//begin deserialization
Document document;
document.Parse(json.c_str());
assert(document.HasMember("lasttradeprice"));
assert(document["hello"].IsString());
std::cout << "The Last Traded Price is = " << document["lasttradeprice"].GetString() << std::endl;
}
/* always cleanup */
curl_easy_cleanup(curl);
}
//timer for URL request. *ADUJST ME AS DESIRED*
usleep(10000000);
}
return 0;
}
//Le Main
int main(void)
{
getData();
}
ios_base is in namespace std. Add prefix std:: before ios_base.
The code below is a test for the CURL C API . The problem is that the callback function write_callback is never called. Why ?
/** compilation: g++ source.cpp -lcurl */
#include <assert.h>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <curl/curl.h>
using namespace std;
static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
std::cerr << "CALLBACK WAS CALLED" << endl;
exit(-1);
return size*nmemb;
}
static void test_curl()
{
int any_data=1;
CURLM* multi_handle=NULL;
CURL* handle_curl = ::curl_easy_init();
assert(handle_curl!=NULL);
::curl_easy_setopt(handle_curl, CURLOPT_URL, "http://en.wikipedia.org/wiki/Main_Page");
::curl_easy_setopt(handle_curl, CURLOPT_WRITEDATA, &any_data);
::curl_easy_setopt(handle_curl, CURLOPT_VERBOSE, 1);
::curl_easy_setopt(handle_curl, CURLOPT_WRITEFUNCTION, write_callback);
::curl_easy_setopt(handle_curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
multi_handle = ::curl_multi_init();
assert(multi_handle!=NULL);
::curl_multi_add_handle(multi_handle, handle_curl);
int still_running=0;
/* lets start the fetch */
while(::curl_multi_perform(multi_handle, &still_running) ==
CURLM_CALL_MULTI_PERFORM );
std::cerr << "End of curl_multi_perform."<< endl;
//cleanup should go here
::exit(EXIT_SUCCESS);
}
int main(int argc,char** argv)
{
test_curl();
return 0;
}
Many thanks
Pierre
You need to check the value of still_running and call curl_multi_perform() again if there are still pending operations.
Simple example:
int still_running=0;
/* lets start the fetch */
do {
while(::curl_multi_perform(multi_handle, &still_running) ==
CURLM_CALL_MULTI_PERFORM);
} while (still_running);