Memory Access error using STK and the FMVoices class - c++

I'm trying to use the STK from Stanford to do some realtime wavetable synthesis. I'm using the FMVoices instrument class https://ccrma.stanford.edu/software/stk/classstk_1_1FMVoices.html
and trying to use it in a callback routine defined below.
int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *dataPointer )
{
FMVoices *FM = (FMVoices *) dataPointer;
register StkFloat *samples = (StkFloat *) outputBuffer;
for ( unsigned int i=0; i<nBufferFrames; i++ )
*samples++ = FM->tick();
return 0;
}
The issue, I think, is with the type of that last parameter. I'm getting a runtime error : "0xC0000005: Access violation executing location 0x000000001." Now, this is the way that the callback is supposed to be written for other STK instruments like Clarinet or even the FileLoop class, but there's something funky about FMVoices. The object is passed to openStream (which handles platform specific realtime output) as a pointer to void. The callback is called automatically when the system's audio buffer is full. A code snippet that implements this and DOES work for other instruments is shown below:
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
RtAudio dac;
Instrmnt * instrument_FM;
int nFrames = 10000;
try {
instrument_FM = new FMVoices;
}
catch ( StkError & ) {
goto cleanup;
}
instrument_FM->setFrequency(440.0);
// Figure out how many bytes in an StkFloat and setup the RtAudio stream.
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 1;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
unsigned int bufferFrames = RT_BUFFER_SIZE;
try {
dac.openStream( &parameters, NULL, format, (unsigned int)Stk::sampleRate(), &bufferFrames, &tick, (void *)&instrument_FM);
}
catch ( RtError &error ) {
error.printMessage();
Sleep(1000);
goto cleanup;
}
The size of nFrames does not seem to have an effect. It just seemed to me that these types of errors usually come from referencing a pointer to void.

The problem is you are taking the address of a pointer, and passing it into openStream.
// pointer to instrument
Instrmnt * instrument_FM;
// snip ...
// &instrument_FM is a pointer to a pointer! i.e. Instrmnt **
dac.openStream( &parameters, /* other params */, (void *)&instrument_FM)
The quickest solution is to just get rid of the & in that line.
Now some comments on C++, and some more fixes to your code. The code looks like a mixture of C and Java, and opens up a lot of pitfalls to fall into, one of which led to your problem.
There is no need for dynamically allocating FMVoices . Use the stack just like you did for RtAudio dac.
No need to worry about pointers, and deleteing the memory you allocated
Therefore no memory leaks.
Just write FMVoices instrument_FM;
There is no need to do try/catch in most cases for cleanup since C++ has destructors that trigger at the end of scope, and propagate the error.
If you only use the stack, there is no need to worry about delete and having cleanup operations
Don't ever use goto in C++, it's really not needed. (unlike in C, where it could be used for cleanup).
There are destructors and RAII for that.
Use C++ casts which are more fine-grained, such as static_cast<> and reinterpret_cast<>, instead of C-style casts
See this article for an explanation.
Here's the revised code:
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
RtAudio dac;
FMVoices instrument_FM;
instrument_FM.setFrequency(440.0);
// Figure out how many bytes in an StkFloat and setup the RtAudio stream.
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 1;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
unsigned int bufferFrames = RT_BUFFER_SIZE;
// didn't get rid of this try since you want to print the error message.
try {
// note here i need the ampersand &, because instrument_FM is on the stack
dac.openStream( &parameters, NULL, format, static_cast<unsigned int>(Stk::sampleRate()), &bufferFrames, &tick, reinterpret_cast<void*>(&instrument_FM));
}
catch ( RtError& error ) {
error.printMessage();
}
}

Related

ESP32 > using esp_console + argtable3 in a C++ project

I'am developping a C++ project on an ESP32.
I'd like to use esp_console + argtable3 (C libraries) in it.
I'm trying to use argtable3 in my members functions.
To do so, I'm creating callback functions to my members functions with a global pointer.
I'm sure my class is going to be instanced only once so I assume it's ok to create callback functions.
The problem is that argtable isn't giving me back the parameters entered by the user.
It checks for them successfully (number of args and their type) but the data it gives me back is random.
I've tested my code outside of members functions and it works well. But I want to use it inside members functions to access other parts of my object.
Here is my code :
// Pointer for my callback functions
MyClass * _callback;
struct arg_int *argInt;
struct arg_end *endPage;
// My callback function (GLOBAL)
int _setInt(int argc, char *argv[])
{
return _callback->setInt(argc, argv);
}
// Tab of struct for argtable lib (GLOBAL)
void *setInt_argtable[] =
{
argInt = arg_int1(NULL, NULL, "<0-12>", "Integer argument"),
endInt = arg_end(10)
};
// Function I'm calling back
int MyClass::setInt(int argc, char *argv[])
{
int nerrors = arg_parse(argc,argv,setInt_argtable);
if (nerrors > 0)
{
arg_print_errors(stdout, endPage, "myprog");
return 0;
}
printf("argc = %d\n", argc); // argc gives the correct number of args
printf("argv[0] = %s\n", argv[0]); // argv[0] gives the correct command name
printf("argv[1] = %s\n", argv[1]); // argv[1] gives the correct value
printf("argInt->ival[0] = %d\n", argInt->ival[0]); // argInt->ival[0] gives random value
return 0;
}
void MyClass::main(void)
{
// Callback pointer initialisation
_callback = this;
/* Initializing the console */
esp_console_config_t console_config
{
256,
8,
atoi(LOG_COLOR_CYAN),
0
};
ESP_ERROR_CHECK( esp_console_init(&console_config) );
/* Configure linenoise line completion library */
/* Enable multiline editing. If not set, long commands will scroll within
* single line.
*/
linenoiseSetMultiLine(1);
/* Tell linenoise where to get command completions and hints */
linenoiseSetCompletionCallback(&esp_console_get_completion);
linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint);
/* Set command history size */
linenoiseHistorySetMaxLen(100);
esp_console_register_help_command();
//
// Feeding my console with argtable parameters
//
esp_console_cmd_t consoleCmd;
consoleCmd.command = "setInt";
consoleCmd.func = &_setInt;
consoleCmd.help = "Trying to set a integer argument";
consoleCmd.argtable = setInt_argtable;
esp_console_cmd_register(&consoleCmd);
/* Main loop */
while(true)
{
// Getting command from user
}
}
Is my approach of using callback member function good ?
Any idea of what is my problem and how I could solve it ?
Thanks in advance for your answers.
After being copying/pasting very simple sample codes found on internet, I finally found what was the problem :
I was including <argtable3/argtable3.h> after "myclass.h"
It took me almost 2 days for a dumb error...
But if somebody has an explanation about why the inclusion order was allowing me to compile the program but making a "corrupted" binary, feel free to answer !

setjmp, longjump and stack reconstruction

Normally setjmp and longjmp does not care about call stack - instead functions are just preserving and restoring registers.
I would like to use setjmp and longjmp so that call stack would be preserved, and then restored at different executing context
EnableFeature( bool bEnable )
{
if( bEnable )
{
if( setjmp( jmpBuf ) == 0 )
{
backup call stack
} else {
return; //Playback backuped call stack + new call stack
}
} else {
restore saved call stack on top of current call stack
modify jmpBuf so we will jump to new stack ending
longjmp( jmpBuf )
}
Is this kind of approach possible - can someone code me a sample code for this ?
Why I believe by myself it's doable - is because of similar code snipet I have already coded / prototyped:
Communication protocol and local loopback using setjmp / longjmp
There is two call stack running simultaneously - independently from each other.
But just to help you out with this task - I'll give you function for getting callstack for native and managed code:
//
// Originated from: https://sourceforge.net/projects/diagnostic/
//
// Similar to windows API function, captures N frames of current call stack.
// Unlike windows API function, works with managed and native functions.
//
int CaptureStackBackTrace2(
int FramesToSkip, //[in] frames to skip, 0 - capture everything.
int nFrames, //[in] frames to capture.
PVOID* BackTrace //[out] filled callstack with total size nFrames - FramesToSkip
)
{
#ifdef _WIN64
CONTEXT ContextRecord;
RtlCaptureContext( &ContextRecord );
UINT iFrame;
for( iFrame = 0; iFrame < (UINT)nFrames; iFrame++ )
{
DWORD64 ImageBase;
PRUNTIME_FUNCTION pFunctionEntry = RtlLookupFunctionEntry( ContextRecord.Rip, &ImageBase, NULL );
if( pFunctionEntry == NULL )
{
if( iFrame != -1 )
iFrame--; // Eat last as it's not valid.
break;
}
PVOID HandlerData;
DWORD64 EstablisherFrame;
RtlVirtualUnwind( 0 /*UNW_FLAG_NHANDLER*/,
ImageBase,
ContextRecord.Rip,
pFunctionEntry,
&ContextRecord,
&HandlerData,
&EstablisherFrame,
NULL );
if( FramesToSkip > (int)iFrame )
continue;
BackTrace[iFrame - FramesToSkip] = (PVOID)ContextRecord.Rip;
}
#else
//
// This approach was taken from StackInfoManager.cpp / FillStackInfo
// http://www.codeproject.com/Articles/11221/Easy-Detection-of-Memory-Leaks
// - slightly simplified the function itself.
//
int regEBP;
__asm mov regEBP, ebp;
long *pFrame = (long*)regEBP; // pointer to current function frame
void* pNextInstruction;
int iFrame = 0;
//
// Using __try/_catch is faster than using ReadProcessMemory or VirtualProtect.
// We return whatever frames we have collected so far after exception was encountered.
//
__try {
for( ; iFrame < nFrames; iFrame++ )
{
pNextInstruction = (void*)(*(pFrame + 1));
if( !pNextInstruction ) // Last frame
break;
if( FramesToSkip > iFrame )
continue;
BackTrace[iFrame - FramesToSkip] = pNextInstruction;
pFrame = (long*)(*pFrame);
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
}
#endif //_WIN64
iFrame -= FramesToSkip;
if( iFrame < 0 )
iFrame = 0;
return iFrame;
} //CaptureStackBackTrace2
I think it can be modified to obtain actual stack pointer (x64 - eSP and for x32 - there is a pointer already).
Legally, setjmp/longjmp can only be used to jump "back" in the nested call sequence. Which means that it never needs to really "reconstruct" anything - at the moment when you execute the longjmp everything is still intact, right there in the stack. All you need to do is rollback the extra stuff accumulated on top of that between the moment of setjmp and the moment of longjmp.
longjmp automatically does a "shallow" rollback for you (i.e. it simply purges the raw bytes off the top of the stack without calling any destructors). So, if you wanted to do a proper "deep" rollback (like what exceptions do as they fly up the call hierarchy) you'd have to setjmp at each level that needs deep cleanup, "intercept" the jump, perform the cleanup manually and then longjmp further up the call hierarchy.
But this would basically be a manual implementation of "poor-man's exception handling". Why would you want to reimplement it manually? I'd understand if you wanted to do it in C code. But why in C++?
P.S. And yes, setjmp/longjmp are sometimes used in a non-standard way to implement co-routines in C, which does involve jumping "across" and a raw form of stack restoration. But this is non-standard. And in general case it would be much more painful to implement in C++ for the very same reasons that I mentioned above.

Dumping Useful Data to Console on Caught Exception

I have a CExceptionHandler class that is invoked whenever my application detects a run-time exception. For example:
if ( val == NULL )
{
TRACE(_T("Unexpected NULL in sequence."));
AfxThrowException( ERROR_INVALID_DATA );
}
AfxThrowException is very simple:
void AfxThrowException( DWORD error )
{
CExceptionHandler * pException = NULL;
if ( error == 0 )
{
error = ::GetLastError();
}
pException = new CExceptionHandler( error );
TRACE(_T("Warning: throwing CSerialException for error %d\n"), error);
THROW(pException);
}
This is the member Dump function of CExceptionHandler:
void CExceptionHandler::Dump( CDumpContext & dc ) const
{
CObject::Dump(dc);
dc << "m_dwError = " << m_dwError;
}
Higher up in my code I have the try/catch statements:
try
{
/* My app does stuff where the exception is thrown. */
}
catch( CExceptionHandler * ex )
{
afxDump << _T("Dumping exceptional data: ") << _T("\r\n");
ex->Dump( afxDump );
afxDump << _T("\r\n");
}
I would like the collected debug information to be dumped to the console. However, when the PC gets into the catch statement (verified with breakpoint), nothing happens on the console. I am using Visual Studio 2008 in Debug mode. Thoughts are appreciated. Thanks.
CDumpContext sends output to the debugger, not to the console (see OutputDebugString for more information), and if you run under the Visual Studio debugger, the output will appear in the Output window.
If you want to also send output to the console, you can configure CDumpContext to write to a CFile by passing a pointer to a CFile object in the CDumpContext constructor.
If your application is built with the 'Use Multi-Byte Character Set' configuration option, you can use CStdioFile to write to either stdout or stderr:
CStdioFile file(stdout);
CDumpContext dumpContext(&file);
ex->Dump(dumpContext);
Or, if you want to use afxDump, you can set its m_pFile member variable directly (it's declared public). For example you could put this code inside your main function:
CStdioFile file(stdout);
afxDump.m_pFile = &file;
But, this won't work if your app is built as Unicode because strings need to be converted to multi-byte to be written to stdout. To do the conversion, write a class that inherits CFile:
class CDumpFile : public CFile
{
public:
virtual void Write(const void* lpBuf, UINT nCount);
};
void CDumpFile::Write(const void* lpBuf, UINT nCount)
{
// Construct string from array of wide chars
const wchar_t* p = static_cast<const wchar_t*>(lpBuf);
UINT len = nCount / sizeof(wchar_t);
CStringW str(p, len);
CStringA astr(str); // Convert wide char to multibyte
fputs((LPCSTR)astr, stdout); // Write multibyte string to stdout
}
and use it like this:
CDumpFile file;
afxDump.m_pFile = &file;
A couple of other points about your code:
You should ensure that the exception object is deleted in the catch block. If your CExceptionHandler class inherits MFC's CException then you should call ex->Delete(). If it doesn't, you need to delete ex.
I'd advise against using the Afx prefix for own functions - you should consider this reserved for use by the MFC library, in my opinion.
I hope this helps!

Creating a cross-process function pointer

I have a Visual Studio 2008 C++ project for Windows Mobile 6 with two processes. Both of which I would like to have access to the same function which is contained in process1.
That function is Buzz:
struct TEST_STRUCT
{
int bar;
WCHAR foo[ 20 ];
};
typedef int( *pfn_Buzz )( TEST_STRUCT* );
int Buzz( TEST_STRUCT* info );
Process1 contains the definition for Buzz and creates a function pointer for it in a memory-mapped file:
int Buzz( TEST_STRUCT* info )
{
info->bar = 1;
wsprintf( info->foo, L"Hello!" );
return 100;
}
int _tmain( int argc, _TCHAR* argv[] )
{
// create a memory-mapped file shared memory space that can be read by any process
HANDLE mapping = ::CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof( pfn_Buzz ) , NULL );
LPVOID buzz_addr = ::MapViewOfFile( mapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof( pfn_Buzz ) );
// find our process' memory offset
DWORD offset = ::GetCurrentProcessIndex() + 0x02000000;
// copy the complete function address to the shared memory space
buzz_addr = ( LPVOID )( ( DWORD )&Buzz + offset );
// convert the function address to a string to send to process2.exe
WCHAR address[ 9 ] = { 0 };
wsprintf( address, L"%x", ( ( DWORD )buzz_addr ) );
// start process2.exe and wait for it to finish
PROCESS_INFORMATION pi = { 0 };
::CreateProcess( L"\\test_user.exe", address, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi );
::WaitForSingleObject( pi.hProcess, INFINITE );
::UnmapViewOfFile( buzz_addr );
::CloseHandle( mapping );
return 0;
}
Process2 receives the address for Buzz from Process1, casts it to the pfn_Buzz function pointer, and executes it.
// process2.exe
int _tmain( int argc, _TCHAR* argv[] )
{
// get the address of the Buzz() function pointer
WCHAR* wszAddr = argv[ 1 ];
WCHAR* wszAddrEnd = &argv[ 1 ][ 8 ];
DWORD address = wcstol( wszAddr, &wszAddrEnd, 16 );
pfn_Buzz PFNBuzz = ( pfn_Buzz )address;
// execute buzz
TEST_STRUCT test = { 0 };
PFNBuzz( &test );
return 0;
}
Unfortunately, I get an Illegal Instruction exception in process2 when I try to execute the PFNBuzz function.
Can anybody suggest what I could change to get the functionality I'm after?
Thanks,
PaulH
Your problem arises from the fact that Process A (Which starts Process B) have 2 totally different virtual address spaces. You can pass a function pointer to Process A but seeeing as their address spaces are different any pointer you pass will be meaining less to another process. this is one of the huge bonuses of processes.
If you wish to communicate between processes then you will need to use some form of Inter-Process Communication (IPC).
There are several ways of doing IPC under windows. In my opinion the most versatile method is by using sockets. Sockets give you the advantage that you can seperate the machines running Process A and Process B and still get the functionality you want. Equally there is nothing stopping both processes running on the same machine. The flexibility it provides is very useful though.
So assuming you choose a socket based method of IPC then what you are effectively doing is a Remote Procedure Call (RPC).
There are, as you can probably imagine, loads of different ways of doing RPC. You could use DCOM or Corba. Raknet is a third party library that supports RPC. There are numerous other solutions as well. I strongly recommend doing a load of research into the matter. The links and keywords I've provided you with should give you a good starting point :)
You can simply export the function using __declspec(dllexport) and then load it using GetProcAddress() using it's name. If in C++, just remember to extern "C" the declaration to disable name mangling. Consider:
extern "C" int __declspec(dllexport) Buzz( TEST_STRUCT* info ) { ... }
int main ( int, char ** )
{
pfn_Buzz buzz = GetProcAddress(GetModuleHandle(NULL), "Buzz");
// ...
}
Then, pass the function name using the IPC method of your choice.
If you want both processes to use the same function, put the function into a DLL and link that DLL to both processes. Each process has its own address space, so an address in one process may not work at all in another process, and even if it "works" it'll be pointing to something completely different.
Although you're taking/passing the offset into the memory mapped region on the parent side, I don't see any matching code to map the same region and add its base to the pointer when you try to access it on the client side.
Visual C++ has a __based pointer type that can simplify this a bit.

global static boolean pointer causes segmentation fault using pthread

New to pthread programming, and stuck on this error when working on a C++&C mixed code.
What I have done is to call the c code in the thread created by the c++ code. There is a static boolean pointer is_center used in the thread and should got free when the thread finishes.
However I noticed that every time when the program processed into the c function, the value of the boolean pointer would be changed and the segmentation fault then happened due to the free(). And the problem only happens when the c code is used. Remove the c code and the multi-thread c++ part works well.
Detail code is as follows:
static bool *is_center;
// omit other codes in between ...
void streamCluster( PStream* stream)
{
// some code here ...
while(1){
// some code here ...
is_center = (bool*)calloc(points.num,sizeof(bool));
// start the parallel thread here.
// the c code is invoked in this function.
localSearch(&points,kmin, kmax,&kfinal); // parallel
free(is_center);
}
And the function using parallel is as follows (my c code is invoked in each thread):
void localSearch( Points* points, long kmin, long kmax, long* kfinal ) {
pthread_barrier_t barrier;
pthread_t* threads = new pthread_t[nproc];
pkmedian_arg_t* arg = new pkmedian_arg_t[nproc];
pthread_barrier_init(&barrier,NULL,nproc);
for( int i = 0; i < nproc; i++ ) {
arg[i].points = points;
arg[i].kmin = kmin;
arg[i].kmax = kmax;
arg[i].pid = i;
arg[i].kfinal = kfinal;
arg[i].barrier = &barrier;
pthread_create(threads+i,NULL,localSearchSub,(void*)&arg[i]);
}
for ( int i = 0; i < nproc; i++) {
pthread_join(threads[i],NULL);
}
delete[] threads;
delete[] arg;
pthread_barrier_destroy(&barrier);
}
Finally the function calling my c code:
void* localSearchSub(void* arg_) {
int eventSet = PAPI_NULL;
begin_papi_thread(&eventSet);
pkmedian_arg_t* arg= (pkmedian_arg_t*)arg_;
pkmedian(arg->points,arg->kmin,arg->kmax,arg->kfinal,arg->pid,arg->barrier);
end_papi_thread(&eventSet);
return NULL;
}
And from gdb, what I have got for the is_center is:
Breakpoint 2, localSearchSub (arg_=0x600000000000bc40) at streamcluster.cpp:1711
1711 end_papi_thread(&eventSet);
(gdb) s
Hardware watchpoint 1: is_center
Old value = (bool *) 0x600000000000bba0
New value = (bool *) 0xa93f3
0x400000000000d8d1 in localSearchSub (arg_=0x600000000000bc40) at streamcluster.cpp:1711
1711 end_papi_thread(&eventSet);
Any suggestions? Thanks in advance!
Some new information about the code: for the c code, I am using the PAPI package. I write my own papi wrapper to initialize and read system counters. The code is as follows:
void begin_papi_thread(int* eventSet)
{
int thread_id = pthread_self();
// Events
if (PAPI_create_eventset(eventSet)) {
PAPI_perror(return_value, error_string, PAPI_MAX_STR_LEN);
printf("*** ERROR *** Failed to create event set for thread %d: %s\n.", thread_id, error_string);
}
if((return_value = PAPI_add_events(*eventSet, event_code, event_num)) != PAPI_OK)
{
printf("*** ERROR *** Failed to add event for thread %d: %d.\n", thread_id, return_value);
}
// Start counting
if ((return_value = PAPI_start(*eventSet)) != PAPI_OK) {
PAPI_perror(return_value, error_string, PAPI_MAX_STR_LEN);
printf("*** ERROR *** PAPI failed to start the event for thread %d: %s.\n", thread_id, error_string);
}
}
void end_papi_thread(int* eventSet)
{
int thread_id = pthread_self();
int i;
long long * count_values = (long long*)malloc(sizeof(long long) * event_num);
if (PAPI_read(*eventSet, count_values) != PAPI_OK)
printf("*** ERROR *** Failed to load count values.\n");
if (PAPI_stop(*eventSet, &dummy_values) != PAPI_OK) {
PAPI_perror(return_value, error_string, PAPI_MAX_STR_LEN);
printf("*** ERROR *** PAPI failed to stop the event for thread %d: %s.\n", thread_id, error_string);
return;
}
if(PAPI_cleanup_eventset(*eventSet) != PAPI_OK)
printf("*** ERROR *** Clean up failed for the thread %d.\n", thread_id);
}
I don't think you've posted enough code to really understand your problem, but it looks suspicious that you've declared is_center global. I assume you're using it in more than one place, possibly by multiple threads (localSearchSub mentions it, which is your worker thread function).
If is_center is being read or written by multiple threads, you probably want to protect it with a pthread mutex. You say it is "freed when the thread finishes", but you should be aware that there are nprocs threads, and it looks like they're all working on an array of is_center[points] bools. If points != nproc, this could b e a bad thing[1]. Each thread should probably work on its own array, and localSearch should aggregate the results.
The xxx_papi_thread functions don't get any hits on Google, so I can only imagine it's your own... unlikely we'll be able to help you, if the problem is in there :)
[1]: Even if points == nproc, it is not necessarily OK to write to different elements of an array from multiple threads (it's compiler and processor dependent). Be safe, use a mutex.
Also, this is tagged C++. Can you replace the calloc and dynamic arrays (using new) with vectors? It might end up easier to debug, and it certainly ends up easier to maintain. Why do you hate and want to punish the readers of your code? ;)