C++ MySQL Connector PrepareStatement Bad_Access - c++

At runtime in loop by twice, crashed by Bad_Access in while calling PrepareStatement by requesting query.
So I checked the all ResultSet memory and release it all but there is no idea
any idea solve this problem?
Description about member value;
PrepareStatement* pstmt;
ResultSet* res;
and the full code
bool laskdjlaskdj12::RaspBerry::grup_pw_chk(const Json::Value j){
//check the id and group is valid
try{
string group = j["Group"].asString();
const char* id = j["id"].asCString();
string grp;
string pub;
BIO* tmp; //BIO structor to change the RSA* structor
if(group == "NULL"){
group = "";
}
//request the Client is existence
pstmt = con->prepareStatement("SELECT * FROM `raspberry_cli` WHERE `Cli_id` = (?) AND `Cli_Group` = (?)");
pstmt->setString(1, id);
pstmt->setString(2, group);
res = pstmt->executeQuery();
//if query reply is NULL
if(res->next() == false){
std::cout<<"[INFO] : There is no query about raspberry_cli"<<std::endl;
return false;
}
//if query Reply
grp = res->getString("Cli_Group");
pub = res->getString("Cli_Pub");
//if There is no group in Raspberry_pi
if(ras.grp.compare(grp) == false){
//sql의 버퍼 flush
this->SQL_Flush();
return false;
}
// if the group is equal
else{
//save the client information
acc_cli.S_id = id;
acc_cli.S_Group = grp;
//save the client public_key
tmp = BIO_new_mem_buf(pub.c_str(), -1);
acc_cli.Pub_key = PEM_read_bio_RSA_PUBKEY(tmp, NULL, 0, NULL);
//if public key is not wright in section
if(acc_cli.Pub_key == NULL){
return false;
}
delete[] tmp;
//flush SQL_flush = delete ResultSet
this->SQL_Flush();
return true;
}
}catch(sql::SQLException& e){
std::cout << "# ERR: SQLException in " << __FILE__;
std::cout << "(" << __FUNCTION__ << ") on line "<< __LINE__ << std::endl;
std::cout << "# ERR: " << e.what();
std::cout << " (MySQL error code: " << e.getErrorCode();
std::cout << ", SQLState: " << e.getSQLState() << " )" << std::endl;
return false;
}
The Detal StackTrace is this
* thread #1: tid = 0x2778b, 0x00000001000e29c3 RaspBerry`list_add(root=0x0000000100903e38, element=0x00000001009043e8) + 19 at list.c:33, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x00000001000e29c3 RaspBerry`list_add(root=0x0000000100903e38, element=0x00000001009043e8) + 19 at list.c:33 [opt]
frame #1: 0x00000001000de27f RaspBerry`mysql_stmt_init(mysql=0x0000000102802220) + 143 at libmysql.c:1568 [opt]
frame #2: 0x0000000100168f41 RaspBerry`sql::mysql::NativeAPI::MySQL_NativeConnectionWrapper::stmt_init(this=0x0000000100a00580) + 33 at mysql_native_connection_wrapper.cpp:421 [opt]
frame #3: 0x000000010011c415 RaspBerry`sql::mysql::MySQL_Connection::prepareStatement(this=0x0000000100a00550, sql=0x00007fff5fbfe138) + 53 at mysql_connection.cpp:1137 [opt]
* frame #4: 0x0000000100073071 RaspBerry`laskdjlaskdj12::RaspBerry::grup_pw_chk(this=0x00007fff5fbfeba0, j=const Json::Value # 0x00007fff5fbfea30) + 881 at RaspBerry.cpp:438
frame #5: 0x000000010007c222 RaspBerry`main(argc=1, argv=0x00007fff5fbff7f8) + 3474 at main.cpp:81
frame #6: 0x00007fffced8b255 libdyld.dylib`start + 1
frame #7: 0x00007fffced8b255 libdyld.dylib`start + 1

Find the answer
pstmt = con->prepareStatement("SELECT * FROM `raspberry_cli` WHERE `Cli_id` = (?) AND `Cli_Group` = (?)");
pstmt->setString(1, id);
pstmt->setString(2, group);
res = pstmt->executeQuery();
[delete pstmt;] //===================> This part is missing
in this section i didn't delete pstmt(sql::preparestatement*)
so the sql have send that malloc error.
So Be careful about allocating memory.

Related

Reading delta values from R&H spectrum analysers

I am currently working on a project where I need to read the difference between the minimum
and maximum markers of a Rhode and Schwarz FSC3 device. I am using NIVisa to connect to the
device over an ethernet connection and pass SCPI commands to it.
The operating system I am using is Ubuntu 20.04.
The code I am using is as shown below -
// Gloabl Visa ResouceManager reference
VisaResourceManager rm;
/**
* Custom type that defines a relation between the deviceIP string
* and a session_t within the Resource Manager
**/
typedef std::map<std::string, VisaResourceManager::session_t> deviceIpSessionMap_t;
deviceIpSessionMap_t devices;
bool device_exists(const std::string deviceIP)
{
deviceIpSessionMap_t::iterator iter = devices.find(deviceIP);
if (iter != devices.end())
{
return true;
}
else
{
return false;
}
}
// --------------------------------------------------------
// Struct defining the ReadConfiguration which is required
// to get readings from the device
// --------------------------------------------------------
struct ReadConfig
{
// The center frequency for the reading
std::string center;
// The span for the reading
std::string span;
// rbw value for reading
std::string rbw;
// vbw value for reading
std::string vbw;
// IP address of the X-pole device
std::string ip;
};
/**
* This function retrieves values from the
* spectrum analyser
*/
int getValueFromDevice(ReadConfig &conf)
{
try
{
//-----------------------------------------------------------
// Set SCPI commands strings
//-----------------------------------------------------------
std::string DeviceIP = "TCPIP::" + conf.ip;
std::string CenterFreq = "FREQ:CENT " + conf.center + "KHz";
std::string Span = "FREQ:SPAN " + conf.span + "KHz";
std::string Rbw = "BAND " + conf.rbw + "KHz";
std::string Vbw = "BAND:VID " + conf.vbw + "Hz";
// logConf(DeviceIP, CenterFreq, Span, Rbw, Vbw);
// Check if the session already exists and reuse it
// if available. If not create a new session and add it
// to the deviceIP to session map
VisaResourceManager::session_t session;
if (device_exists(conf.ip))
{
session = devices[conf.ip];
}
else
{
session = rm.connect(DeviceIP);
devices[conf.ip] = session;
}
session->write("*RST;*CLS\n"); // Reset and clear the device
//-----------------------------------------------------------
// ID the device:
//-----------------------------------------------------------
// session->write("*IDN?");
// std::cout << "status byte = " << session->readSTB() << std::endl;
// std::cout << "*IDN? = " << session->read() << std::endl;
// std::cout << "status byte = " << session->readSTB() << std::endl;
//-----------------------------------------------------------
// Basic Device Settings:
//-----------------------------------------------------------
session->write(CenterFreq); // Setting the center frequency
session->write(Span); // Setting the span
session->write(Rbw); // Setting the RBW
session->write(Vbw); // Setting the VBW
session->write("CALC:DELT1 OFF"); // Removes/resets MARK2 position
session->write("CALC:DELT2 OFF"); // Removes/resets MARK2 position
session->write("CALC:MARK1 OFF"); // Removes/resets MARK1 position
session->write("CALC:MARK2 OFF"); // Removes/resets MARK1 position
session->write("*OPC?"); // Using *OPC? waits until all the instrument settings are finished
//-----------------------------------------------------------
// Setting marker to min and reading the marker Y
//-----------------------------------------------------------
session->write("CALC:DELT1:MIN");
session->write("CALC:MARK1:MAX");
session->write("*OPC?");
session->write("CALC:DELT1:Y?\n");
std::string min = session->read();
int iMin = abs(std::stoi(min));
// std::cout << "iMin : " << iMin << '\n';
//-----------------------------------------------------------
// Disconnect from Device
//-----------------------------------------------------------
// rm.disconnect(session);
return iMin;
}
catch (VisaException ex)
{
std::cout << ex.what() << " -- " << VisaResourceManager::statusDescription(ex.getErrorCode()) << std::endl;
return 0;
}
catch (...){
std::cout << "Encountered an unknown error" << std::endl;
return 0;
}
}
This usually shows me the correct values, but when the analyzer has been on for a while it starts
malfunctioning/reporting absurd values that are too high.
What am I doing wrong ?

Sqlite C API in multiprocess

I'm testing Sqlite C Api for multiprocess concurrency and I'm hitting a bug that I don't understand.
The test is simple: 1 database, 1 table of 1000 rows with 2 columns. Column 1 are uuids, column 2 is a status set to 0. I'm launching then 2 workers that concurrently select 2 uuids at status 0 and update them to 1 until no uuids are left to be updated.
Here the code in the main loop of the worker:
std::vector<std::string> uuids;
res = sqlite3_exec(database,
"BEGIN IMMEDIATE TRANSACTION;", nullptr, nullptr, nullptr);
if (res != SQLITE_OK)
{
Log("Worker: Failed to begin transaction, wait for other worker to finish");
std::this_thread::sleep_for(std::chrono::milliseconds(5));
continue;
}
Log("Worker: Begin Transaction");
// SELECT UUIDS
std::string selectString = "SELECT " + m_uuidStr + " FROM " + m_tableStr + " WHERE " + m_statusStr + "=" + std::to_string(0) + " LIMIT " + std::to_string(2);
// Log("Worker: SelectString = " + selectString);
auto selectStatement = selectString.c_str();
res = sqlite3_exec(database,
selectStatement,
fill_uuids,
&uuids, nullptr);
if (res != SQLITE_OK)
{
Log("Worker: Failed to select uuids");
return 3;
}
if (uuids.empty())
{
sqlite3_exec(database, "ROLLBACK;", nullptr, nullptr, nullptr);
Log("Worker: nothing more to update");
break;
}
// UPDATE UUIDS
std::stringstream ss;
ss << '\"' << uuids[0] << '\"';
for (int i = 1; i < uuids.size(); ++i)
ss << ", \"" << uuids[i] << '\"';
Log("Worker: UUIDs selected = " + ss.str());
std::string updateString = "UPDATE " + m_tableStr
+ " SET " + m_statusStr + "=" + std::to_string(1)
+ " WHERE (" + m_uuidStr + " in (" + ss.str() + ")) AND (" + m_statusStr + "=" + std::to_string(0) + ");";
auto updateStatement = updateString.c_str();
// BIG CRASH HERE WITH IMMEDIATE TRANSACTION ///
res = sqlite3_exec(database,
updateStatement,
nullptr, nullptr, nullptr);
if (res != SQLITE_OK)
{
Log("Worker: Failed to update uuids, err = " + std::string(err));
return 4;
}
// COMMIT CHANGES
res = sqlite3_exec(database,
"COMMIT;", nullptr, nullptr, nullptr);
if (res != SQLITE_OK)
{
Log("Worker: Failed to commit, err = " + std::string(err));
return 5;
}
Log("Worker: Transaction ended");
When using immediate transactions, one of the worker crashes with a negative error code (-1073741819 but I doubt it helps) when executing the UPDATE statement. When using exclusive transactions, I don't have any crash. The version with immediate transactions works with a unique worker. The database is open using the flags SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, Sqlite is compiled with option SQLITE_THREADSAFE=1.
There are no other process accessing the database while the workers are running. In that respect I don't understand why immediate transactions causes a crash and exclusive transactions do not, as the behavior should be similar (since no thread/process is creating reading statement during the worker execution).
I'm very new to Sqlite so maybe there's an obvious mistake lying in my code. Any help is appreciated.

Finding SQL server deadlock cause

I have a simple c++ program running on MSVC using an ODBC connection to execute a stored procedure.
When running it on the main thread it works fine, but when I attempt to multithread the same class I am getting this error:
(Process ID XX) was deadlocked on lock resource....
As mentioned above I can run it fine on the main thread and also on two threads with no issues.
This is how I spawn, use and join the threads:
historical apple("AAPL");
historical google("GOOG");
historical yahoo("YHOO");
historical samsung("005930.KS");
historical ibm("IBM");
auto t1 = thread([&] {apple.go(); });
auto t2 = thread([&] {google.go(); });
auto t3 = thread([&] {yahoo.go(); });
auto t4 = thread([&] {samsung.go(); });
auto t5 = thread([&] {ibm.go(); });
//writer(his.getHistorical()); // this writes to the file test.csv
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
I know it looks like shit, but I'm basically trying to see how hard I can push the software before making it look nice and more formatted.
This is how I call the stored procedure:
#include "stdafx.h"
#include "database_con.h"
////////////////////////////////////////////////////////////////////////
// Show errors from the SQLHANDLE
void database_con::show_error(unsigned int handletype, const SQLHANDLE& handle)
{
SQLWCHAR sqlstate[1024];
SQLWCHAR message[1024];
if (SQL_SUCCESS == SQLGetDiagRec(handletype, handle, 1, sqlstate, NULL, message, 1024, NULL))
wcout << "Message: " << message << "\nSQLSTATE: " << sqlstate << endl;
}
////////////////////////////////////////////////////////////////////////
// Builds the stored procedure query.
std::wstring database_con::buildQuery(vector<std::wstring> input, string symbol)
{
std::wstringstream builder;
builder << L"EXEC sp_addHistorical " << "#Symbol='" << L"" << StringToWString(symbol) << "'," <<
"#Date='" << (wstring)L"" << input.at(0) << "'," <<
"#Open=" << (wstring)L"" << input.at(1) << "," <<
"#Close=" << (wstring)L"" << input.at(2) << "," <<
"#MaxPrice=" << (wstring)L"" << input.at(3) << "," <<
"#MinPrice=" << (wstring)L"" << input.at(4) << "," <<
"#Volume=" << (wstring)L"" << input.at(5) << ";";
return builder.str();
}
////////////////////////////////////////////////////////////////////////
// Adds a substring of the string before the delimiter to a vector<wstring> that is returned.
std::vector<wstring> database_con::parseData(wstring line, char delim) {
size_t pos = 0;
std::vector<std::wstring> vOut;
while ((pos = line.find(delim)) != std::string::npos) {
vOut.push_back(line.substr(0, pos));
line.erase(0, pos + 1);
}
vOut.push_back(line.substr(0, pos));
return vOut;
}
////////////////////////////////////////////////////////////////////////
// Converts a std::string to a std::wstring
std::wstring database_con::StringToWString(const std::string& s)
{
std::wstring temp(s.length(), L' ');
std::copy(s.begin(), s.end(), temp.begin());
return temp;
}
void database_con::historicalLooper(string historical) {
}
////////////////////////////////////////////////////////////////////////
// Constructs a database connector object with the historical data and its symbol
database_con::database_con(std::string historical, string symbol){
/*
Set up the handlers
*/
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN */
SQLDriverConnectW(dbc, NULL, L"DRIVER={SQL Server};SERVER=ERA-PC-STUART\\JBK_DB;DATABASE=master;UID=geo;PWD=kalle123;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
/* Check for success */
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt))
{
show_error(SQL_HANDLE_DBC, dbc);
std::cout << "Failed to connect";
}
_mSymbol = symbol;
std::wstringstream stream(StringToWString(historical));
std::wstring line;
int row = 0;
while (std::getline(stream, line)) {
if (row > 0) {
vector<wstring> vHistorical = parseData(L"" + line, ',');
std::wstring SQL = buildQuery(vHistorical, _mSymbol);
if (SQL_SUCCESS != SQLExecDirectW(stmt, const_cast<SQLWCHAR*>(SQL.c_str()), SQL_NTS)) {
std::cout << "Execute error " << std::endl;
show_error(SQL_HANDLE_STMT, stmt);
std::wcout << L"Unsuccessful Query: " << SQL << std::endl;
}
// Close Cursor before next iteration starts:
SQLRETURN closeCursRet = SQLFreeStmt(stmt, SQL_CLOSE);
if (!SQL_SUCCEEDED(closeCursRet))
{
show_error(SQL_HANDLE_STMT, stmt);
// maybe add some handling for the case that closing failed.
}
}
row++;
}
std::cout << "Query " << _mSymbol << " ready" << std::endl;
}
database_con::~database_con() {
}
And finally this is the stored procedure:
GO
CREATE PROCEDURE sp_addHistorical
#Symbol nchar(10),#Date datetime,
#Open decimal(12,2),#Close decimal(12,2),#MinPrice decimal(12,2),
#MaxPrice decimal(12,2),#Volume int
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
MERGE HistoricalStock WITH (UPDLOCK) AS myTarget
USING (SELECT #Symbol AS Symbol,
#Date AS Date, #Open AS [Open], #Close AS [Close],
#MinPrice AS MinPrice, #MaxPrice AS MaxPrice,#Volume AS Volume) AS mySource
ON mySource.Symbol = myTarget.Symbol AND mySource.Date = myTarget.Date
WHEN MATCHED
THEN UPDATE
SET [Open] = mySource.[Open], [Close] = mySource.[Close],
MinPrice = mySource.MinPrice, MaxPrice = mySource.MaxPrice, Volume = mySource.Volume
WHEN NOT MATCHED
THEN
INSERT(Symbol,Date,[Open],[Close],MinPrice,MaxPrice,Volume)
VALUES(#Symbol,#Date,#Open,#Close,#MinPrice,#MaxPrice,#Volume);
COMMIT
GO
Any sort of help or advice on either how it's all structured or pointers to good examples regarding the issue I'm facing would be greatly appreciated.
I'm somewhat new to SQL server (more importantly to stored procedures) and can't really figure out what is wrong, even though I understand what a deadlock is.
Thanks!

Converting (parsing) google protocol buffer streams from socket

I am using the following code to parse a message that was SerializedwithCodedStream on to the socket:
if ( socket->read(databuffer, size) != -1)
{
google::protobuf::io::ArrayInputStream array_input(databuffer,size);
google::protobuf::io::CodedInputStream coded_input(&array_input);
data_model::terminal_data* tData = new data_model::terminal_data();
if (!tData->ParseFromCodedStream(&coded_input))
{
return;
}
else
std::cout << tData->symbol_name() << std::endl;
}
Here is how I serialized it:
data_model::terminal_data tData;
tData.set_type(1);
tData.set_client_id("C109");
tData.set_expiry("20140915");
tData.set_quantity(3500);
tData.set_strat_id("056");
tData.set_symbol_name("BANKNIFTY");
tData.set_time("145406340");
tData.set_trade_id(16109234);
int total_size = tData.ByteSize() + sizeof(int);
char *buffer = new char[total_size];
memset(buffer, '\0', total_size);
google::protobuf::io::ArrayOutputStream aos(buffer,total_size);
google::protobuf::io::CodedOutputStream *coded_output = new google::protobuf::io::CodedOutputStream(&aos);
google::protobuf::uint32 s = tData.ByteSize();
coded_output->WriteVarint32(s);
tData.SerializeToCodedStream(coded_output);
int sent_bytes = 0;
if ( (sent_bytes = send(liveConnections.at(i), buffer, total_size, MSG_NOSIGNAL)) == -1 )
liveConnections.erase(liveConnections.begin() + i);
else
std::cout << "sent " << sent_bytes << " bytes to " << i << std::endl;
delete coded_output;
delete buffer;
When I try to parse, it gives the following error at runtime:
[libprotobuf ERROR google/protobuf/message_lite.cc:123] Can't parse message of type "data_model.terminal_data" because it is missing required fields: type
But as you can see (in the second code snippet) I have set the type field. What is the problem ?
You're ignoring the count returned by read(), other than checking it for -1. You need to use it instead of size when constructing array_input.

Processing large files with libsndfile

Currently I've written a program (in Visual Studio C++) based on the available example code of "libsndfile" in which I've just added a subtraction-function to subtract one (channel of a) WAV-file with another.
The program worked perfectly for files with a limit of 4 channels.
The problem is that as soon as I upload a file with as many as 5 channels or more, the program refuses to execute the function. This is independent of the frame-size as I've managed to process 4-channel files which were many times larger than some 5/6-channel-files which I have used.
Has anyone encountered this or a similar problem before? If requested I will provide the source code.
My apologies for the bad structure, I don't really optimize until I get the whole deal working.
Code:
#include <sndfile.hh>
#include <tinyxml2.h>
#include <iostream>
#include <fstream>
#define BLOCK_SIZE 32
using TiXmlDocument = tinyxml2::XMLDocument;
using CStdStringA = std::string;
int main(int argc, char* argv[])
{
SNDFILE *infile = NULL;
SNDFILE *infile2 = NULL;
SNDFILE *outfile = NULL;
SF_INFO sfinfo;
SF_INFO sfinfo2;
SF_INFO sfinfoOut;
sf_count_t readcount;
//int filetype = SF_FORMAT_WAV | SF_FORMAT_PCM_24; // 24-bit Wav-Files
TiXmlDocument iDoc; // Init tinyXML
int i; // Iteration-var;
short BufferIn[BLOCK_SIZE]; // Buffer1
short BufferIn2[BLOCK_SIZE]; // Buffer2
short BufferOut[BLOCK_SIZE];
CStdStringA FileLoc, FileName, FileLocWav, FileLocTxt,FileLocRaw; // OutputFile locationstring
CStdStringA WavName, WavName2, FileIn, FileIn2;
FileLoc = "C:\\Testfiles\\";
//TextTitle(FileLoc); // Print console-header
printf("Name Wavefile 1:\n");
std::cin >> WavName;
FileIn = FileLoc + WavName + ".wav";
if((infile = sf_open(FileIn.c_str(),SFM_READ,&sfinfo)) == NULL) // Open Wav-file 2 instance
{
printf("Not able to open input file 1\n");
printf("\n\nPress any key to exit."); // Exit-text if file not present
puts(sf_strerror(NULL)) ;
return 1;
}
std::cout << "Wav file 1 succesfully opened." << std::endl;
std::cout << "\nChannels: " << sfinfo.channels << "\nFrames: " << sfinfo.frames << std::endl; // Print Channels & Frames
std::cout << "Samplerate: " << sfinfo.samplerate << "\n\n" << std::endl;// Print Samplerate
printf("Name Wavefile 2:\n");
std::cin >> WavName2;
FileIn2 = FileLoc + WavName2 + ".wav";
if((infile2 = sf_open(FileIn2.c_str(),SFM_READ,&sfinfo2)) == NULL) // Open Wav-file 2 instance
{
printf("Not able to open input file 2\n");
printf("\n\nPress any key to exit."); // Exit-text if file not present
puts(sf_strerror(NULL)) ;
return 1;
}
std::cout << "Wav file 2 succesfully opened." << std::endl;
std::cout << "\nChannels: " << sfinfo2.channels << "\nFrames: " << sfinfo2.frames << std::endl; // Print Channels & Frames
std::cout << "Samplerate: " << sfinfo2.samplerate << "\n\n" << std::endl;// Print Samplerate
//{
//std::cout << "Format differs from eachother, abort program.";
//printf("\n\nPress any key to exit."); // Exit-text
//return 1;
//}
if(sfinfo.channels != sfinfo2.channels) // Abort if channels not the same
{
std::cout << "Channelammount differs from eachother, abort program.";
printf("\n\nPress any key to exit."); // Exit-text
return 1;
}
if(sfinfo.samplerate != sfinfo2.samplerate) // Abort if samplerate not the same
{
std::cout << "Samplerate differs from eachother, abort program.";
printf("\n\nPress any key to exit."); // Exit-text
return 1;
}
std::cout << "Give a filename for Txt- & Wav-file: ";
std::cin >> FileName;
FileLoc += FileName; // Fuse Filelocation with given name
FileLocTxt = FileLoc + ".txt";
FileLocWav = FileLoc + ".wav";
FileLocRaw = FileLoc + "Raw.txt";
sfinfoOut.channels = sfinfo.channels;
sfinfoOut.format = sfinfo.format;
sfinfoOut.samplerate = sfinfo.samplerate;
if((outfile = sf_open(FileLocWav.c_str(),SFM_WRITE,&sfinfoOut)) == NULL) // Open Wav-file 2 instance
{
printf("Not able to create output file \n");
printf("\n\nPress any key to exit."); // Exit-text if file not present
puts(sf_strerror(NULL)) ;
return 1;
}
std::ofstream myfile;
myfile.open(FileLocTxt.c_str(),std::ios::app);
std::ofstream myfileRaw;
myfileRaw.open(FileLocRaw.c_str(),std::ios::app);
while((readcount = sf_read_short(infile, BufferIn, BLOCK_SIZE))) // While there are still frames to be processed
{
//process_data (data, readcount, sfinfo.channels) ;
auto readcount2 = sf_read_short(infile2, BufferIn2, BLOCK_SIZE);
for(i = 0; i < BLOCK_SIZE; i++) // BLOCK_SIZE decides the chunk-size
{
BufferOut[i] = BufferIn[i] - BufferIn2[i];
myfileRaw << BufferOut[i];
}
sf_write_short(outfile, BufferOut, BLOCK_SIZE) ; // Write the data to a new file
}
sf_close(infile); // Close Wav-file handlers
sf_close(infile2);
sf_close(outfile);
myfile.close(); // Close text-file handlers
printf("\n\nPress any key to exit."); // Exit-text
return 0;
}
The documentation states:
File Read Functions (Items)
sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
The file read items functions fill the array pointed to by ptr with the requested number of items. The items parameter must be an integer product of the number of channels or an error will occur
There's your problem, since BLOCK_SIZE is a multiple of 1,2,4 but not of 3 and 5 - so that would fail.
About the problem that program completes as if calculations had taken place: add appropriate error handling.