struct SourceInfo {
const char *filename;
int line, col;
};
struct Node;
struct Lexer {
private:
FILE *File;
std::string Filename;
char* test;
int Line;
int Column;
static const int MAX_LINE_LENGTH = 1024;
public:
Lexer(FILE* in, const char* filename)
{
File = in;
test = new char[strlen(filename)+1];
strcpy(test, filename);
Filename = std::string(test);
Line = 0;
Column = 0;
}
~Lexer() {
}
Node *next() {
return nullptr;
}
Node *peek() {
return nullptr;
}
SourceInfo get_current_pos() {
SourceInfo info;
info.filename = Filename.c_str();
info.line = Line;
info.col = Column;
return info;
}
};
////////////////////////////////////////////////////////////////////////
// Lexer API functions
////////////////////////////////////////////////////////////////////////
struct Lexer *lexer_create(FILE *in, const char *filename) {
return new Lexer(in, filename);
}
void lexer_destroy(struct Lexer *lexer) {
delete lexer;
}
struct Node *lexer_next(struct Lexer *lexer) {
return lexer->next();
}
struct Node *lexer_peek(struct Lexer *lexer) {
return lexer->peek();
}
struct SourceInfo lexer_get_current_pos(struct Lexer *lexer) {
return lexer->get_current_pos();
}
/* The setup function creates the test fixture. */
TestObjs* setup();
/* The cleanup function cleans up the test fixture. */
void cleanup(TestObjs* objs);
//Test functions
void testCreate(TestObjs* objs);
void testGetCurrentPosAtBeginning(TestObjs* objs);
int main(int argc, char** argv) {
if (argc > 2) {
printf("Usage: %s [<test name>]\n", argv[0]);
return 1;
}
/*
* If a command line argument is passed, it's the name
* of the test to be executed.
*/
if (argc == 2) {
tctest_testname_to_execute = argv[1];
}
/*
* Install test execution hook.
* (Only test suites that need to do detailed monitoring or
* reporting of test execution will need to do this.)
*/
//tctest_on_test_executed = onTestExecuted;
/*
* Install completion hook.
* (Only test suites that need to do something special
* to report results really need to do this: TEST_FINI
* generates a reasonable human-readable summary of
* the executed tests.
*/
//tctest_on_complete = onComplete;
/* Prepare to run tests */
TEST_INIT();
/* Execute test functions */
TEST(testCreate);
TEST(testGetCurrentPosAtBeginning);
/*
* Report results: exits with nonzero exit code if
* any test failed
*/
TEST_FINI();
}
TestObjs* setup() {
TestObjs* objs = malloc(sizeof(TestObjs));
return objs;
}
void cleanup(TestObjs* objs) {
lexer_destroy(objs->lexer);
free(objs);
}
void testCreate(TestObjs* objs) {
const char *filename = "testFile.txt\0";
objs->filename = (char*) malloc(sizeof(char) * (strlen(filename) + 1));
strcpy(objs->filename, filename);
FILE* in = fopen(objs->filename, "r");
objs->lexer = lexer_create(in, objs->filename);
}
void testGetCurrentPosAtBeginning(TestObjs* objs) {
struct SourceInfo info = lexer_get_current_pos(objs->lexer);
ASSERT(info.line == 0);
ASSERT(info.col == 0);
ASSERT(strcmp(objs->filename, info.filename) == 0);
free(info.filename);
}
For some reason, I am getting a segmentation fault in testGetCurrentPosAtBeginning function. I do not why this error is occurring because I managed the memory properly. I looked through GDB and was puzzled as to why this error is occurring.
To me, it looks like memory is going out of scope at the constructor but I am not sure. The test functions are based off of TCTest, a test framework for C.
For some reason, I am getting a segmentation fault in
testGetCurrentPosAtBeginning function. I do not why this error is
occurring because I managed the memory properly.
It is occurring because you are not managing memory properly.
In particular, testGetCurrentPosAtBeginning() does this:
free(info.filename);
You must free only pointer values obtained from malloc() or another memory-allocation function, but if we trace the source of info.filename, it ultimately comes from
info.filename = Filename.c_str();
in method Lexer::get_current_pos(). This is not a string you should attempt to free.
Related
Here is what my program currently looks like. I have to add history functionality that gets stored in a file 'mysh.history'. Currently I expect my output to simply append each user command in my shell to the file.
first line of output
first line of output
It only appends the first input into the shell instance. I think my problem lies with my understanding of the fork() process but I'm not sure what is going on. Any suggestions?
#define MYSH_BUFFERSIZE 64
#define MYSH_DELIM " \t\n"
fstream file;
// custom function declarations
int mysh_exit(char **args);
int mysh_add_history(char **args);
int mysh_history(char **);
char byebye[] = "byebye";
char exit_program[] = "exit";
char history[] = "history";
// contains names of all custom shell commands implemented
char *lookup_str[] = {byebye, exit_program, history};
// holds references to all commands in lookup_str[]
// order or commands must match each other
int (*lookup_func[])(char **) = {
&mysh_exit,
&mysh_exit,
&mysh_history
};
/* custom shell commands implementations BEGIN*/
// Without the argument, it prints out the recently typed commands (with their
// arguments), in reverse order, with numbers
// If the argument ā-cā is passed, it clears the list of recently typed commands.
void clear_history()
{
file.close();
file.open("mysh.history", ios::trunc);
}
int mysh_add_history(char *line)
{
// if exists then append to the history
if (access("mysh.history", F_OK) == 0)
{
file.open("mysh.history", ios::app);
}
// otherwise create mysh.history and start writing
else
{
file.open("mysh.history", ios::out);
}
file << line << "\n";
return 0;
}
int mysh_history(char **)
{
return 0;
}
int mysh_exit(char **args)
{
return 0;
}
int num_commands()
{
return sizeof(lookup_str) / sizeof(char *);
}
/* custom shell functions END*/
/* main shell processes BEGIN*/
// returns the tokens (arguments) array after tokenizing line from mysh_read_line()
char **mysh_split_args(char *line)
{
int buffer_size = MYSH_BUFFERSIZE;
int current_pos = 0;
char **tokens = (char **)malloc(buffer_size * sizeof(char *));
char *tok;
if (!tokens)
{
printf("mysh: memory allocation error\n");
exit(EXIT_FAILURE);
}
tok = strtok(line, MYSH_DELIM);
while (tok != NULL)
{
tokens[current_pos] = tok;
current_pos++;
if (current_pos >= buffer_size)
{
buffer_size += MYSH_BUFFERSIZE;
tokens = (char **)realloc(tokens, buffer_size * sizeof(char *));
if (!tokens)
{
printf("mysh: memory allocation error\n");
exit(EXIT_FAILURE);
}
}
tok = strtok(NULL, MYSH_DELIM);
}
tokens[current_pos] = NULL;
return tokens;
}
// mysh_read_line allocates MYSH_BUFFER_SIZE of memory to the intial buffer
// it reallocates memory as needed with getLine() function
// returns line to be processed and tokenized by mysh_split_args()
char *mysh_read_line(void)
{
char *line = NULL;
size_t buffersize = 0;
// getLine() also needs to check for EOF after in the case of text files being read.
if (getline(&line, &buffersize, stdin) == -1)
{
if (feof(stdin))
{
exit(EXIT_SUCCESS);
}
else
{
printf("failed to read line\n");
exit(EXIT_FAILURE);
}
}
return line;
}
// args passed comes from mysh_split_args()
int mysh_launch_process(char **args)
{
pid_t pid;
pid_t wpid;
int state;
pid = fork();
// if we enter child process
if (pid == 0)
{
if (execvp(args[0], args) == -1)
{
printf("error in mysh\n");
}
exit(EXIT_FAILURE);
}
// forking failed
else if (pid < 0)
{
printf("error in mysh\n");
}
else
{
// if we enter parent process
do
{
wpid = waitpid(pid, &state, WUNTRACED);
} while (!WIFEXITED(state) && !WIFSIGNALED(state));
}
return 1;
}
// calls mysh_launch_process() and handles programs being called
int mysh_execute(char **args)
{
int i;
if (args[0] == NULL)
{
return 1;
}
for (i = 0; i < num_commands(); i++)
{
if (strcmp(args[0], lookup_str[i]) == 0)
{
if (strcmp(args[0], "history") == 0 && strcmp(args[1], "-c"))
{
clear_history();
}
return (*lookup_func[i])(args);
}
}
return mysh_launch_process(args);
}
void mysh_loop(void)
{
char *line;
char **args;
int state;
do
{
printf("# ");
line = mysh_read_line();
mysh_add_history(line);
args = mysh_split_args(line);
state = mysh_execute(args);
free(line);
free(args);
} while (state);
}
int main(int argc, char **argv)
{
// run main program loop
mysh_loop();
file.close();
return EXIT_SUCCESS;
}
/* main shell processes END*/```
I have a problem with (at least) one row in my code. My intention is to instantiate some objects for HTTP requests. I store their pointers in an array requestsBatch because I will call them from within a helper function. After storing them I'll do some time checks and then send the request to the server. After a successful request, the object will be deleted.
It seems the variable address is problematic but I can't see why.
const char* root_ca_sherz = "myCert";
int currentRequestsBatchIndex=0;
class HTTPREQUESTS {
public:
HTTPREQUESTS(String strAddress = "", String strParameters = "", bool bSendImmediately=false, const char* cert=root_ca_sherz) {
address = strAddress;
parameters = strParameters;
certificate = cert;
currentRequestsBatchIndex++;
Serial.println("New object instantiated");
Serial.println(address);
Serial.println(parameters);
}
~HTTPREQUESTS() {
currentRequestsBatchIndex--;
}
bool sendRequest() {
Serial.println("Called from within sendRequest()");
Serial.println(address); // <<<<<< THIS ROW CAUSES THE REBOOT
/*
http.begin(address+"/"+parameters, certificate); //, root_ca_sherz
int httpCode = http.GET();
Serial.print("HTTP Code: ");
Serial.println(httpCode);
Serial.print("Payload: ");
Serial.println(http.getString());
if (httpCode > 0) { //Check for the returning code
return true;
}
else {
Serial.println("Error on HTTP request");
return false;
}
http.end();
delay(1000);
return false;
*/
return true;
}
private:
const char* certificate="";
String parameters;
String device;
String address;
unsigned long timestamp=0;
int sendAttempts=0;
bool sendImmediately = false;
unsigned long lastSendAttemp=0;
};
HTTPREQUESTS *requestsBatch[5];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(3000);
Serial.println("Ready");
String address = "https://myAddress.com";
String parameters = "?secret=XXXXX&deviceName=deviceName&status=1&value=999&time=123456789&functionName=functionName";
HTTPREQUESTS *req01 = new HTTPREQUESTS(address, parameters);
// Store pointer to array to use it later
requestsBatch[currentRequestsBatchIndex] = req01;
Serial.println("Object stored in array");
Serial.print(F("Send request: "));
if(requestsBatch[0]->sendRequest()) {
//delete requestsBatch[0];
Serial.println("requestsBatch[0] deleted");
}
}
void loop() {
// put your main code here, to run repeatedly:
}
SOLUTION:
Replacing
currentRequestsBatchIndex++;
by
if(address != "") {
currentRequestsBatchIndex++;
}
because currentRequestsBatchIndex is also incrementing when creating the empty *requestsBatch[5] array.
As I dont like the String class (will cause you memory problems later on)I rewrote with char arrays and it works as expected (Included your "solution" but have you checked serial monitor output):
const char* root_ca_sherz = "myCert";
char address[128] = {'\0'};
int currentRequestsBatchIndex = 0;
class HTTPREQUESTS {
public:
HTTPREQUESTS(char strAddress[128] = {'\0'}, char strParameters [128] = {'\0'}, bool bSendImmediately = false, const char* cert = root_ca_sherz) {
strcpy (address, strAddress);
strcpy (parameters, strParameters);
certificate = cert;
if (address[0] != '\0') {
currentRequestsBatchIndex++;
}
currentRequestsBatchIndex++;
Serial.println("New object instantiated");
Serial.println(address);
Serial.println(parameters);
}
~HTTPREQUESTS() {
currentRequestsBatchIndex--;
}
bool sendRequest() {
char testAddress [128] = {'\0'};
Serial.println("Called from within sendRequest()");
strcpy (testAddress, address);
Serial.print("Will work: ");
Serial.println(testAddress); // <<<<<< THIS ROW CAUSES THE REBOOT
Serial.print("Will also work: ");
Serial.println(address); // but over written at next creation
/*
http.begin(address+"/"+parameters, certificate); //, root_ca_sherz
int httpCode = http.GET();
Serial.print("HTTP Code: ");
Serial.println(httpCode);
Serial.print("Payload: ");
Serial.println(http.getString());
if (httpCode > 0) { //Check for the returning code
return true;
}
else {
Serial.println("Error on HTTP request");
return false;
}
http.end();
delay(1000);
return false;
*/
return true;
}
private:
const char* certificate = "";
char parameters[128] = {'\0'};
char device[128] = {'\0'};
// char address[128] = {'\0'};
unsigned long timestamp = 0;
int sendAttempts = 0;
bool sendImmediately = false;
unsigned long lastSendAttemp = 0;
};
HTTPREQUESTS *requestsBatch[5];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(3000);
Serial.println("Ready");
const char address[] = "https://myAddress.com";
const char parameters[] = "?secret=XXXXX&deviceName=deviceName&status=1&value=999&time=123456789&functionName=functionName";
HTTPREQUESTS *req01 = new HTTPREQUESTS(address, parameters);
// Store pointer to array to use it later
requestsBatch[currentRequestsBatchIndex] = req01;
Serial.println("Object stored in array");
Serial.print(F("Send request: "));
if (requestsBatch[0]->sendRequest()) {
//delete requestsBatch[0];
Serial.println("requestsBatch[0] deleted");
}
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("Still running !");
delay(1000);
}
I have following run time error sometimes (not all the times)
malloc: * error for object 0x14: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
else
EXE_BAD_ACCESS ( EXC_I386_GPFLT)
on the same line of code.
Please help me to solve this trouble.
I have following structure for curl based server connector.
in curlBasedServerConnector.cpp see the place where >>>ERROR POINTED HERE line appear.
curlBasedServerConnector.hpp
class curlBasedServerConnector : public webServiceConnectorInterfaceA
{
private:
CURLcode curlCode;
CURL* curlHandle;
char* messagePtr;
std::string message = "";
static std::atomic<int> totalNumOfCurlProcesses;
static std::atomic<bool> isGlobalInitCalledAlready;
static std::mutex curlGlobalInitKey;
static size_t writeContents_s(char *buf, size_t size, size_t nmemb, void *up)
{
curlBasedServerConnector* pThis = static_cast<curlBasedServerConnector*>(up);
return pThis->writeContents(buf, size, nmemb);
}
// member version
size_t writeContents(char* buf, size_t size, size_t nmemb)
{
std::copy(buf, buf+(size*nmemb), std::back_inserter(message));
return size*nmemb;
}
public:
bool executeOperation()override ;
bool openConnection() override;
bool setHttpHeader(const char* contentType, const char* charSet)override;
bool setServerUrl(const char* url)override;
void setRequest(const char* request)override;
void closeConnection() override;
std::string getResponseAsString()override;
bool listenToNotification()override;
void setTrace(bool trace);
int getNumberofCurlProcessesInitialized();
curlBasedServerConnector()
{
curlGlobalInitKey.lock();
{
if(!isGlobalInitCalledAlready)
{
curlCode = curl_global_init(CURL_GLOBAL_ALL);
cout<<" Server Connector GLOBAL_INIT CALLED "<<endl;
isGlobalInitCalledAlready = true;
totalNumOfCurlProcesses++;
}
else
{
totalNumOfCurlProcesses++;
}
}
curlGlobalInitKey.unlock();
openConnection();
}
virtual ~curlBasedServerConnector(){
curlGlobalInitKey.lock();
totalNumOfCurlProcesses--;
if(totalNumOfCurlProcesses == 0)
{
curl_global_cleanup();
}
curlGlobalInitKey.unlock();
}
};
curlBasedServerConnector.cpp
bool curlBasedServerConnector::openConnection(){
bool successStatus = false;
if(curlHandle )
{
cout<<"curl hanlde --"<<curlHandle<<endl;
successStatus = true;
}
else
{
curlHandle = curl_easy_init();
if(curlHandle != NULL){
successStatus = true;
}
}
cout<<"openConnection() CURL CODE "<<curlCode<<endl;
return successStatus;
}
void curlBasedServerConnector::closeConnection(){
curl_easy_cleanup(curlHandle);
}
bool curlBasedServerConnector::setServerUrl(const char *url){
cout<<"curl handle at setting url "<<curlHandle<<endl;
curlCode = curl_easy_setopt(curlHandle, CURLOPT_URL, url); >>>ERROR POINTED HERE
bool successStatus = false;
if(curlCode == 0 | curlCode == CURLE_OK)
{
successStatus = true;
}
else if (curlCode == 27 | curlCode == CURLE_OUT_OF_MEMORY){
exit(8);
}
return successStatus;
}
webServiceConnectorInterfaceA.hpp
class webServiceConnectorInterfaceA
{
public:
virtual bool openConnection() = 0;
virtual bool executeOperation()= 0; //
virtual bool setHttpHeader(const char* contentType, const char* charSet) = 0;
virtual bool setServerUrl(const char* url)=0;
virtual void setRequest(const char* request)=0;
virtual void closeConnection() = 0;
virtual bool listenToNotification() = 0;
virtual std::string getResponseAsString()=0;
webServiceConnectorInterfaceA(){ };
~webServiceConnectorInterfaceA(){ };
};
I have accessor class which compose this class as following
class webServiceAccessor{
private:
const char* serverAddress = "http://localhost:2000";
std::shared_ptr<sharedQueue> gmsListenerQueue;
std::shared_ptr<webServiceConnectorInterfaceA> webServiceConnectorInterface;
webServiceAccessor(){}
~webServiceAccessor(){}
}
Why it throws such error on the same line ?
Who cause this error curlBasedServerConnector class or class webServiceAccessor ?
How to solve this or debug this?
I am using C++11 in Xcode IDE.
Thanks
Trace when using malloc guard:
GuardMalloc[TIFAR2-5307]: Allocations will be placed on 16 byte boundaries.
GuardMalloc[TIFAR2-5307]: - Some buffer overruns may not be noticed.
GuardMalloc[TIFAR2-5307]: - Applications using vector instructions (e.g., SSE) should work.
GuardMalloc[TIFAR2-5307]: version 108
TIFAR2(5307,0x100c31000) malloc: protecting edges
TIFAR2(5307,0x100c31000) malloc: stack logs being written into /tmp/stack-logs.5307.102c4c000.TIFAR2.M7TEpU.index
TIFAR2(5307,0x100c31000) malloc: recording malloc and VM allocation stacks to disk using standard recorder
TIFAR2(5307,0x100c31000) malloc: enabling scribbling to detect mods to free blocks
TIFAR2(5307,0x100c31000) malloc: process 5239 no longer exists, stack logs deleted from /tmp/stack-logs.5239.102c4c000.TIFAR2.YFARFr.index
WEB SERVICE CONNECTION STARTS HERE ......
webServiceConnectorInterfaceA constructtor called
.
.
.
I'm using MS Visual Studio 2015 to develop a small app using VC++ and backend as SQLite. However using standard SQLite3 C api there are no exceptions occurring.
But when i tried to make a small wrapper for using SQLite. I made one header file for simplification for using functions as SQLite APIs. I'm getting read access violation exception.
How to handle this exception and what changes i should make in my small wrapper so i can use it in multiple modules of the app.
here is my small wrapper SQLite.cpp:
#include "inc\sqlite3.h"
#include <string.h>
#pragma once
class SQLiteConnection {
sqlite3 * conn;
public:
SQLiteConnection() {
conn = NULL;
}
~SQLiteConnection() {
sqlite3_close(conn);
}
int connect(char const * dbName) {
int res = sqlite3_open(dbName, &conn);
if (SQLITE_OK != res) {
printf("%s\n", sqlite3_errmsg(conn));
return res;
}
return res;
}
sqlite3 * getConn() {
return conn;
}
};
class Statement {
sqlite3_stmt * stmt;
public:
Statement() {
stmt = NULL;
}
int prepare(sqlite3 *,char *);
int bind_param_int(sqlite3 *,int , int);
int bind_param_text(sqlite3 * ,int , char const *);
int bind_param_double(sqlite3 * ,int , double);
bool step();
int reset();
char const * getColText(int idx);
void finalize() {
sqlite3_finalize(stmt);
}
};
int Statement::prepare(sqlite3 * conn, char *sql) {
int result;
result = sqlite3_prepare_v2(conn, sql, -1, &stmt, NULL);
if (SQLITE_OK != result) {
sqlite3_errmsg(conn);
return 0;
}
return SQLITE_OK;
}
int Statement::bind_param_int(sqlite3 * conn,int idx, int val) {
int res;
res = sqlite3_bind_int(stmt, idx, val);
if (SQLITE_OK != res) {
sqlite3_errmsg(conn);
return 0;
}
return SQLITE_OK;
}
int Statement::bind_param_text(sqlite3 * conn, int idx, char const * val) {
int res;
res = sqlite3_bind_text(stmt, idx, val, strlen(val)+1, SQLITE_STATIC);
if (SQLITE_OK != res) {
sqlite3_errmsg(conn);
return 0;
}
return SQLITE_OK;
}
int Statement::bind_param_double(sqlite3 * conn , int idx, double val) {
int res;
res = sqlite3_bind_double(stmt, idx, val);
if (SQLITE_OK != res) {
sqlite3_errmsg(conn);
return 0;
}
return SQLITE_OK;
}
bool Statement::step() {
int res = sqlite3_step(stmt);
if (SQLITE_DONE == res) return true;
if (SQLITE_ROW == res) return true;
return false;
}
int Statement::reset() {
int res = sqlite3_reset(stmt);
if (SQLITE_OK == res) return res;
return 0;
}
char const * Statement::getColText(int idx) {
return (char const *)sqlite3_column_text(stmt, idx);
}
Here is my main app.cpp file
#include <iostream>
#include <stdio.h>
using namespace std;
/*
* SQLite3 header file
* for getting Constants for verification of results.
*/
#include "inc\sqlite3.h"
#include "SQLite.h"
int main() {
SQLiteConnection con;
try {
if (SQLITE_OK == con.connect(":memory:")) {
cout << "Connected to DB";
Statement stmt;
if (SQLITE_OK == stmt.prepare(con.getConn(), "select 'Hello World'")) {
while (stmt.step())
{
cout << "\n" << stmt.getColText(0) << "\n";
}
stmt.finalize();
}
}
else {
return 1;
}
}
catch (const exception & e) {
cout << "Exception..."<< e.what();
}
getchar();
return 0;
}
Started first time in Visual C++ and SQLite3 so the knowledge level is beginner and I also don't know much about Modern C++ and STL ;( will learn soon..
Hoping that brilliant minds will explain me what is happening here and how will I be able to get out from that.
read access violation exception.
I dont think this is a C++ exception, it is rather hardware exception caused by the fact that your code tries to access memory it should not. It should be generated with additional information like address which might give some hints on the cause of the problem.
How to handle this exception
well, you dont :-) or rather you can't, your app must crash. You might actually write exception handler which could write stack trace to some log file, or make a dump file for later analysis. In large application programmers add lots of logging to at least allow testers to send them log files which might help in finding what application was doing when crash happend.
and what changes i should make in my small wrapper so i can use it in multiple modules of the app.
hard to tell because you should use debugger to find a place when it crashes. Maybe you are using some uninitialized memory, or wrongly using API. Your select statement looks strange, is it correct? But probably it should not crash application. Your destructor looks also suspicious, sqlite3_close(conn); is called even if conn is NULL.
If this is related to your other question where you say you tried getting values even when SQLite returns SQLITE_DONE then that is the answer. With that code the stepping has finished and there is nothing to read so reading anyway may cause nasty crashes. You may only read with the code SQLITE_ROW.
Your code returns true on step even when stepping is finished, remove that from the code.
FILE.CPP: I am using this file and to use this I have created object "myFile"
/*
SD - a slightly more friendly wrapper for sdfatlib
This library aims to expose a subset of SD card functionality
in the form of a higher level "wrapper" object.
License: GNU General Public License V3
(Because sdfatlib is licensed with this.)
(C) Copyright 2010 SparkFun Electronics
*/
#include <SD.h>
/* for debugging file open/close leaks
uint8_t nfilecount=0;
*/
File::File(SdFile f,
const char *n) {
// oh man you are kidding me, new() doesnt exist? Ok we do it by hand!
_file=(SdFile *)malloc(sizeof(SdFile));
if (_file) {
memcpy(_file, &f, sizeof(SdFile));
strncpy(_name, n, 12);
_name[12]=0;
/* for debugging file open/close leaks
nfilecount++;
Serial.print("Created \"");
Serial.print(n);
Serial.print("\": ");
Serial.println(nfilecount, DEC);
*/
}
}
File::File(void) {
_file=0;
_name[0]=0;
//Serial.print("Created empty file object");
}
File::~File(void) {
// Serial.print("Deleted file object");
}
// returns a pointer to the file name
char *File::name(void) {
return _name;
}
// a directory is a special type of file
boolean File::isDirectory(void) {
return (_file && _file->isDir());
}
size_t File::write(uint8_t val) {
return write(&val, 1);
}
size_t File::write(const uint8_t *buf,
size_t size) {
size_t t;
if (!_file) {
setWriteError();
return 0;
}
_file->clearWriteError();
t=_file->write(buf,
size);
if (_file->getWriteError()) {
setWriteError();
return 0;
}
return t;
}
int File::peek() {
if (! _file) return 0;
int c=_file->read();
if (c !=-1) _file->seekCur(-1);
return c;
}
int File::read() {
if (_file) return _file->read();
return -1;
}
// buffered read for more efficient, high speed reading
int File::read(void *buf,
uint16_t nbyte) {
if (_file) return _file->read(buf, nbyte);
return 0;
}
int File::available() {
if (! _file) return 0;
uint32_t n=size() - position();
return n > 0X7FFF ? 0X7FFF: n;
}
void File::flush() {
if (_file) _file->sync();
}
boolean File::seek(uint32_t pos) {
if (! _file) return false;
return _file->seekSet(pos);
}
uint32_t File::position() {
if (! _file) return -1;
return _file->curPosition();
}
uint32_t File::size() {
if (! _file) return 0;
return _file->fileSize();
}
void File::close() {
if (_file) {
_file->close();
free(_file);
_file=0;
/* for debugging file open/close leaks
nfilecount--;
Serial.print("Deleted ");
Serial.println(nfilecount, DEC);
*/
}
}
File::operator bool() {
if (_file) return _file->isOpen();
return false;
}
I am trying to create a SD card read write package using Simulink. What happens is here is I would take SD.cpp and SD.h and other required files and create a wrapper file which consists of required operation (i.e. reading and writing to SD card) and I am getting the following errors
SDcard_wrapper.cpp: In function 'void SDcard_Update_wrapper(const boolean_T*, real_T*, const uint8_T*, int_T)':
./SDcard_wrapper.cpp:113: error: no match for 'operator=' in 'myFile = SDClass::open(const char*, uint8_t)(((const char*)"test.txt"), 19u)'
C:\Users\Samanth\Documents\MATLAB\newSD-trail/utility/SdFat.h:135: note: candidates are: SdFile& SdFile::operator=(const SdFile&)
./SDcard_wrapper.cpp:123: error: could not convert 'myFile' to 'bool'
Following is the SDcard_wrapper.cpp error locations:
myFile = SD.open("test.txt", FILE_WRITE); //This is the line where I am getting 1st error
if (myFile) // this is the point where I am getting the error: could not convert 'myFile' to 'bool'
{
Serial.print("Writing to test.txt...");
myFile.println("testing 1, 2, 3.");
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
File SDClass::open(const char* filepath, uint8_t mode) {
/*
Open the supplied file path for reading or writing.
The file content can be accessed via the `file` property of
the `SDClass` object--this property is currently
a standard `SdFile` object from `sdfatlib`.
Defaults to read only.
If `write` is true, default action (when `append` is true) is to
append data to the end of the file.
If `append` is false then the file will be truncated first.
If the file does not exist and it is opened for writing the file
will be created.
An attempt to open a file for reading that does not exist is an
error.
*/
int pathidx;
// do the interative search
SdFile parentdir = getParentDir(filepath, &pathidx);
// no more subdirs!
filepath += pathidx;
if (!filepath[0]) {
// it was the directory itself!
return File(parentdir, "/");
}
// Open the file itself
SdFile file;
// failed to open a subdir!
if (!parentdir.isOpen())
return File();
// there is a special case for the Root directory since its a static dir
if (parentdir.isRoot()) {
if (!file.open(SD.root, filepath, mode)) {
// failed to open the file :(
return File();
}
// dont close the root!
} else {
if (!file.open(parentdir, filepath, mode)) {
return File();
}
// close the parent
parentdir.close();
}
if (mode & (O_APPEND | O_WRITE))
file.seekSet(file.fileSize());
return File(file, filepath);
}
class SdFile : public Print // This is the line pointed above in the second error just for information SdFat.h:135: note: candidates are: SdFile& SdFile::operator=(const SdFile&)
{
public:
/** Create an instance of SdFile. */
SdFile(void): type_(FAT_FILE_TYPE_CLOSED) {}
/**
* writeError is set to true if an error occurs during a write().
* Set writeError to false before calling print() and/or write() and check
* for true after calls to print() and/or write().
*/
//bool writeError;
/**
* Cancel unbuffered reads for this file.
* See setUnbufferedRead()
*/
void clearUnbufferedRead(void) {
flags_ &= ~F_FILE_UNBUFFERED_READ;
}
uint8_t close(void);
uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
uint8_t createContiguous(SdFile* dirFile, const char* fileName, uint32_t size);
/** \return The current cluster number for a file or directory. */
uint32_t curCluster(void) const {
return curCluster_;
}
/** \return The current position for a file or directory. */
uint32_t curPosition(void) const {
return curPosition_;
}
static void dateTimeCallback(void(*dateTime)(uint16_t* date, uint16_t* time)) {
dateTime_ = dateTime;
}
/**
* Cancel the date/time callback function.
*/
static void dateTimeCallbackCancel(void) {
// use explicit zero since NULL is not defined for Sanguino
dateTime_ = 0;
}