Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

CTL32 LIBCURL - NOT ENOUGH MEMORY...

Status
Not open for further replies.

bournerj

Programmer
Jun 11, 2015
2
GB
Hi

I'm currently implementing Carlos's Ctl32 libcurl library in our application and am experiencing some strange behaviour on the 26th call to the function -- namely, the "There is not enough memory to complete this operation." error.

As far as I'm aware, I'm cleaning up as I should and I've seen this error before with errors that weren't actually caused by memory leaks so I'm not 100% convinced that it's a leak.

I can replicate this behaviour and have separated everything out so it is just this code that is running -- every 26th call creates this error and then I have to close the IDE in order to be able to run a successful call again -- this is even after running the following:


Code:
CLEAR ALL
CLEAR RESOURCES
CLEAR MEMORY
SET DEFAULT TO
SET CLASSLIB TO
CLOSE ALL
RELEASE ALL



This is me using my own wrapper to run a simple GET on our website:


Code:
SET PROCEDURE TO RC_Curl ADDITIVE

loRCCurl = CREATEOBJECT("RCCurl", "[URL unfurl="true"]https://rushcliff.com")[/URL]
loRCCurl.Get()

IF loRCCurl.bGotAnError
	??loRCCurl.cError
	RETURN .f.
ENDIF

??loRCCurl.cReturn

RELEASE loRCCurl
RELEASE PROCEDURE RC_Curl



The RCCurl class:


Code:
DEFINE CLASS RCCurl AS Custom
	PROTECTED oCurl, oError, nResultCode, cRawReturn
	oCurl = .null.
	oError = .null.
	nResultCode = -1
	cRawReturn = ""
	
	bGotAnError = .f.
	cError = ""
	cReturn = ""
	
	FUNCTION Init
		PARAMETERS cURL

		DO libcurl.prg

		this.oCurl = CREATEOBJECT("libcurl")
		
		IF !EMPTY(cURL)
			this.SetURL(cURL)
		ENDIF
		
		this.oCurl.CurlOptSslVerifyHost = .f.
		this.oCurl.CurlOptSslVerifyPeer = .f.
		
		RETURN .t.
	ENDFUNC
	
	FUNCTION Destroy
		this.oCurl = .null.
		RELEASE CLASSLIB libcurl.vcx
	ENDFUNC
	
	PROTECTED FUNCTION SetError
		PARAMETERS cError
		
		this.bGotAnError = .t.
		this.cError = "Error: " + ALLTRIM(cError)
	ENDFUNC
	
	FUNCTION GetURL
		RETURN this.oCurl.CurlOptURL
	ENDFUNC
	
	FUNCTION SetURL
		PARAMETERS cURL
		
		this.oCurl.CurlOptURL = cURL
	ENDFUNC
	
	PROTECTED FUNCTION WeGotAnError
		RETURN .f.
	ENDFUNC
	
	PROTECTED FUNCTION Run
		IF EMPTY(this.GetURL())
			this.SetError("Destination URL is not set.")
			RETURN .f.
		ENDIF
		
		*!* Run that thang.
		this.nResultCode = this.oCurl.CurlEasyPerform()
		
		IF this.nResultCode <> 0
			*!* Error!
			this.SetError(ALLTRIM(STR(this.nResultCode)) + " " + this.oCurl.CurlEasyStrError(this.nResultCode))
			RETURN .f.
		ENDIF
		
		this.cReturn = this.oCurl._databuffer
		
		RETURN .t.
	ENDFUNC
	
	*!* HTTP GET
	FUNCTION Get
		PARAMETERS cURL
		
		IF !EMPTY(cURL)
			this.SetURL:cURL)
		ENDIF
		
		this.oCurl.CurlOptHttpGet = .t.

		IF !this.Run()
			RETURN .f.
		ENDIF
		
		IF this.WeGotAnError()
			RETURN .f.
		ENDIF
		
		RETURN .t.
	ENDFUNC
ENDDEFINE


The libcurl.prg and .vcx have not been modified.

The line that causes this error (called from rccurl.init >> rccurl.seturl >> libcurl.curlopt_assign >> libcurl.curlglobalinit >> libcurl._createcallbacks) is:



Code:
This._DebugCallBackPtr = ;
CreateCallBackFunc("_DebugCallback","INTEGER","INTEGER,INTEGER,INTEGER,INTEGER,INTEGER", This, 1)



if I ignore on that line, the subsequent CreateCallBackFunc calls produce the same error.

For reference, my development machine is W7 64-bit.

Any help is greatly appreciated, many thanks in advance.

Richard
 
Hi Richard,

I have a typo there in this.SetURL:cURL), but no, that's not the fix.
I can reproduce, but I get the memory error at DestroyCallbackFunc in _destroycallbacks method of the libcurl class in libcurl.vcx
I can't tell you what's wrong, I don't know if this usage of getting at _databuffer is correct, the underline seems to indicates an internal property, but it's obviously not private or hidden.
The usaual use of curls easyperform is in conjunction with a callback function, as it works asynchhronous, you get parts of the currently running operation(s).

Maybe use HttpDownloadFile instead.

Bye, Olaf.
 
Hi Olaf

Thanks for your response.

The typo isn't in my actual code, must have found its way in during copy/paste.

Interesting, it is on CreateCallBackFunc every time for me.

I'll look at the callback option then, thanks.

I want to set up for running POST and PUT calls as well so thought this would be the best option. Failing that I'll probably use Rick's wwClient.

Thanks again,

Richard
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top