|
Thank Albert and Richard .
I am now reading "advanced-linux-programming" book and compile by gcc .
Thanks
Thong LT .
|
|
|
|
|
Hi, I read an old program, the programmer wrote some function like the following block, I am wonder if the volatile is necessary with a local variable.
As I know, local variable is in stack, every time enter the function, local variable get a new stack address.
void logRealClock(void)
{
volatile int second;
volatile int minute;
volatile int hour;
second = globalDate->second;
minute = globalDate->minute;
hour = globalDate->hour;
....
checkTime(second,minute,hour);
...
globalRTC_REG.second = second;
globalRTC_REG.minute = minute;
globalRTC_REG.hour = hour;
}
|
|
|
|
|
|
Thanks,I read the Wiki article, but I still can't see the need of volatile for local variable.
The example code only cause size of generated assembly code bigger, but useless.
int main() {
volatile int a = 10, b = 100, c = 0, d = 0;
printf("%d", a + b);
a = b;
c = b;
d = b;
printf("%d", c + d);
return 0;
}
|
|
|
|
|
If you pass a pointer to your variable outside the function (for example to an interrupt handler) and then you guarantee the lifetime of that variable (for example by blocking on an event with this thread) and you want to use the variable in the function after finishing the block operation on the event then it could be useful (because the value of the variable might have been changed by other threads) but what I've described previously sounds quite pervert and awfully designed code. I don't think volatile local vars to be useful.
|
|
|
|
|
thanks, what you said like:
volatile int* aPtr = aSharedMem;
right? then in another thread,
aSharedMem = aNewValue;
then in the current thread, stalled before aSharedMem=aNewValue, then resume, *aPtr get the aNewValue.
if local variable just copy a global's value, like:
volatile int aLocal = aGlobal;
then in another thread, aGlobal = aNewValue;
in current thread, stalled before aGlobal = aNewValue, then resume, aLocal will get aNewValue?
|
|
|
|
|
int* globalptr;
void myfunc()
{
volatile int localvar = 0;
globalptr = &localvar;
printf("localvar: %d\n", localvar);
}
|
|
|
|
|
is the following scenario, the volatile is useful?
int globalVar;
void task1SetGlobal(void)
{
if (xyz == 100)
globalPtr = 100;
}
...
void task2GetGlobal(void)
{
volatile int localVar = 0;
localVar = globalVar;
if (localVar < 100 ) doSth;
else if (localVar == 100) do100Thing;
}
|
|
|
|
|
Not really. In order to understand volatile you should first understand some other concepts like multithreading and caching and all the related problems that can cause problems along with the optimizations done by the compiler.
|
|
|
|
|
It's not necessarily bad design to pass a reference to a local variable to another thread for processing. One example of where it might come in handy is splitting up an array into chunks and processing each chunk in separate threads. However using volatile as a synchronisation mechanism is not the sort of thing I'd recommend to try and avoid a proper synchronisation mechanism (i.e. a condition variable).
|
|
|
|
|
Then we agree, in this case some kind of memory fence is used for synchronization that is usually built into the synch primitives like events. In this case you usually make a function call too to pass the job to another thread and usually this already prevents a compiler from optimizing away some things.
|
|
|
|
|
Probably just me but given the code that was posted I can't see any reason for volatile.
|
|
|
|
|
I have added some code (to an existing MFC/ATL application), to communicate with a piece of hardware that comes complete with com-based driver software.
(Before I forget: I'm writing C++ in Visual Studio 2010, for Windows7).
My code is based closely upon the sample code that the hardware manufacturer supplied, and is as follows;
#import "GlobMgr.dll" no_namespace // I/O funtionality
#import "IviDriverTypeLib.dll" no_namespace // IVI inherent functionality
#import "agu265x.dll" no_namespace // Instrument specific functionality
IAgilentU265xPtr spAgDrvrSlot1;
CCMDS::CCMDS( ...class details not relevant... )
: CUSBDevice( ...ditto... )
{
spAgDrvrSlot1.CreateInstance( __uuidof( AgilentU265x ) );
try
{
spAgDrvrSlot1->Initialize( "USBInstrument1", VARIANT_FALSE, VARIANT_TRUE, "" );
}
catch ( _com_error e )
{
AfxMessageBox( "Driver Initialise Failed" );
}
HOWEVER, my code crashes at the Initialize(USBInstrument1...) statement with a Windows dialog saying Quote: First-chance exception at 0x755bb9bc in IOHandler.exe: Microsoft C++ exception: _com_error at memory location 0x001de4e0..
Why this code fails at all is a mystery but the big question is why does Windows crash with a dialog rather than my Try-Catch code catching the error in the controlled fashion I'd hoped for??
|
|
|
|
|
Presumably something in Windows is catching the error and not re-throwing it. You may wish to talk to the people who provided this code for more help.
Veni, vidi, abiit domum
|
|
|
|
|
Ok, got it thanks - Windows was catching the error and not re-throwing it because... I'm running in Debug and had Visual Studio set to catch all Exceptions
|
|
|
|
|
Something you might have missed: You can set the VC++ debugger up to catch exceptions where they're thrown and it generates a message like the dialogue you're getting. Are you running under the debugger with that setting enabled?
If you're not running under a debugger then it's something else but I thought I'd try and clear that up first!
|
|
|
|
|
Ooops, sorry - I missed your reply earlier! Yes, you were correct - thank-you Feeling like a newbie (again)
|
|
|
|
|
No probs - I only thought about it as I had the same problem last week
|
|
|
|
|
<pre>Dialog box with two buttons, when I drag and drop to another button area swap places. How to do it.
</pre>
|
|
|
|
|
Coding & Googling[^], I suppose.
Veni, vidi, vici.
|
|
|
|
|
shizhanbiao wrote: How to do it. How to do what, exactly? Create a dialog box with two buttons? Implement drag and drop? Swap two buttons? Be specific with what you are asking. It's Wednesday so the mind-reading pills are wearing off.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
Hi all, I read some more on MSDN and found out that if you call a stored proc ( SQL Server in my case ) which returns a record set and also populates an *output* parameter , the parameters return value is in a separate record set. What I did was print all my records then move to the next set with:
spRst = spRst->NextRecordset();
bstr_t NumRecs = ((bstr_t)pCmd->Parameters->Item["Count"]->Value)->GetBSTR();
A lesson learnt.
Hi all, the code below works fine except for the retrieval of the @Count parameter which is of type *output* it always returns zero - any ideas ? ( it's this line of code : _tprintf(_T("Records found = %d\n\n"),spCmd->Parameters["@Count"]);
Many thanks
#pragma region Includes and Imports
#include "stdafx.h"
#include <atlstr.h>
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" rename("EOF","EndOfFile")
using namespace ADODB;
#pragma endregion
static ADODB::_ParameterPtr CreateParam(_bstr_t Name, _bstr_t Value, int Size, ADODB::DataTypeEnum Type, ADODB::ParameterDirectionEnum Direction);
static ADODB::_ParameterPtr CreateParam(_bstr_t Name, int Value, int Size, ADODB::DataTypeEnum Type, ADODB::ParameterDirectionEnum Direction);
int _tmain(int argc, _TCHAR* argv[])
{
if (argc < 4)
{
_tprintf(_T("Usage: CppUseADO.exe \"Search for this\" Y|N to specify combined or not Y|N to include address search\n"));
return -1;
}
int i = 0;
::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
ADODB::_ConnectionPtr spConn = NULL;
ADODB::_RecordsetPtr spRst = NULL;
ADODB::_CommandPtr spCmd = NULL;
ADODB::_ParameterPtr spParam = NULL;
_bstr_t bstrSearchExp(argv[1]);
_bstr_t bstrCombined(argv[2]);
_bstr_t bstrSearchAddress(argv[3]);
_bstr_t bstrConn("dsn=CMS;");
try
{
spConn.CreateInstance(__uuidof(ADODB::Connection));
_tprintf(_T("Connecting to the database ...\n"));
spConn->Open(bstrConn, "", "", NULL);
spCmd.CreateInstance(__uuidof(ADODB::Command));
spCmd->ActiveConnection = spConn;
spCmd->CommandText = "SearchOnCreditorName";
spCmd->CommandType = ADODB::adCmdStoredProc;
spRst.CreateInstance(__uuidof(ADODB::Recordset));
spParam = CreateParam("@PartWord", bstrSearchExp, 35, ADODB::adVarChar, ADODB::ParameterDirectionEnum::adParamInput);
spCmd->Parameters->Append(spParam);
spParam = CreateParam("@Combined", bstrCombined, 1, ADODB::adChar, ADODB::ParameterDirectionEnum::adParamInput);
spCmd->Parameters->Append(spParam);
spParam = CreateParam("@SearchAddress", bstrSearchAddress, 1, ADODB::adChar, ADODB::ParameterDirectionEnum::adParamInput);
spCmd->Parameters->Append(spParam);
spParam = CreateParam("@Count", 0, 8, ADODB::adInteger, ADODB::ParameterDirectionEnum::adParamReturnValue);
spCmd->Parameters->Append(spParam);
_tprintf(_T("Searching the CMS Database for value %s \n"), (PCTSTR)bstrSearchExp);
spCmd->Prepared = true;
spRst = spCmd->Execute(NULL, NULL, NULL);
_tprintf(_T("Records found = %d\n\n"),spCmd->Parameters["@Count"]);
while (!spRst->EndOfFile)
{
variant_t vtClaimRef(spRst->Fields->Item["ClaimRef"]->Value);
variant_t vtCreditorName(spRst->Fields->Item["CreditorName"]->Value);
variant_t vtAddr1(spRst->Fields->Item["AddrLine1"]->Value);
variant_t vtAddr2(spRst->Fields->Item["AddrLine2"]->Value);
variant_t vtAddr3(spRst->Fields->Item["AddrLine3"]->Value);
_tprintf(_T("%s\t %s\t %s %s %s\n"),
vtClaimRef.vt == VT_NULL ? _T("(DBNull)") : (PCTSTR)vtClaimRef.bstrVal,
vtCreditorName.vt == VT_NULL ? _T("(DBNull)") : (PCTSTR)vtCreditorName.bstrVal,
vtAddr1.vt == VT_NULL ? _T("(DBNull)") : (PCTSTR)vtAddr1.bstrVal,
vtAddr2.vt == VT_NULL ? _T("(DBNull)") : (PCTSTR)vtAddr2.bstrVal,
vtAddr3.vt == VT_NULL ? _T("(DBNull)") : (PCTSTR)vtAddr3.bstrVal);
i++;
spRst->MoveNext(); // Move to the next record
}
_tprintf(_T("%d records printed for %s\n"), i, (PCTSTR)bstrSearchExp);
}
catch (_com_error err)
{
_tprintf(_T("\nOops something went wrong ! probably no records found\n"));
_tprintf(err.Description());
_tprintf(err.ErrorMessage());
_tprintf(_T("\n\n"));
}
/////////////////////////////////////////////////////////////////////////
// Clean up objects before exit.
//
_tprintf(_T("Closing the connection...\n"));
// Close the record set if it is open
if (spRst && spRst->State == ADODB::adStateOpen)
spRst->Close();
// Close the connection to the database if it is open
if (spConn && spConn->State == ADODB::adStateOpen)
spConn->Close();
::CoUninitialize();
return 0;
}
static ADODB::_ParameterPtr CreateParam(_bstr_t Name, _bstr_t Value, int Size, ADODB::DataTypeEnum Type, ADODB::ParameterDirectionEnum Direction)
{
ADODB::_ParameterPtr spParam;
spParam.CreateInstance(__uuidof(ADODB::Parameter));
spParam->Direction = Direction;
spParam->Name = Name;
spParam->Type = Type;
spParam->Size = Size;
spParam->Value = Value;
return spParam;
}
static ADODB::_ParameterPtr CreateParam(_bstr_t Name, int Value, int Size, ADODB::DataTypeEnum Type, ADODB::ParameterDirectionEnum Direction)
{
ADODB::_ParameterPtr spParam;
spParam.CreateInstance(__uuidof(ADODB::Parameter));
spParam->Direction = Direction;
spParam->Name = Name;
spParam->Type = Type;
spParam->Size = Size;
spParam->Value = Value;
return spParam;
}
We can’t stop here, this is bat country - Hunter S Thompson RIP
modified 6-Nov-13 2:40am.
|
|
|
|
|
I cannot find a reference for the CreateParam function anywhere so it's difficult to check your settings. Also, it would help if you put <pre> tags around your code.
Veni, vidi, abiit domum
|
|
|
|
|
OK, sorry Richard ' the CreateParam function is a UDF , I included it in the code sample - also I didn't know about the
tag
<div class="signature">We can’t stop here, this is bat country - Hunter S Thompson RIP</div>
|
|
|
|
|
pkfox wrote: also I didn't know about the
tag
Select the text, and click either the "code" or "var" link above the message box. I would add to this that most of the code you've shown is not relevant to the problem. Only include what is absolutely necessary so that more folks will read your post.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|