Passing char pointer to function ruins pointer - c++

I am having some difficulties with a bluetooth/oled display displaying the right string. The goal is to read data from bluetooth, update a class variable(Music.setArtist()), and then read from that variable later(Music.getArtist()) to draw it using a draw text function.
If i only call drawText once, it works fine. More than one calls in a loop to drawText cause some undefined behavior though, which is usually the second pointer getting overwritten. This causes the pointer in drawText to be null, or some random characters, or something.
This is my music object.
#ifndef Music_h
#define Music_h
class Music {
private:
char *track,*artist,*length, *position;
int progressBar;
bool playing;
public:
Music(char* t, char* a, char* l, char* po, bool pl, int p): track(t), artist(a), length(l), position(po), playing(pl), progressBar(p){};
~Music(){};
char* getLength(){return length;}
char* getPosition(){return position;}
char* getArtist(){return artist;}
char* getTrack(){return track;}
bool getPlaying(){return playing;}
int getProgressBar(){return progressBar;}
void setLength(char * l){length = l;}
void setPosition(char *p){position = p;}
void setArtist(char *a){artist = a;}
void setTrack(char *t){track = t;}
void setPlaying(bool p){playing = p;}
void setProgressBar(int p){progressBar = p;}
};
#endif
This is my drawText function
void Display_obj::drawText(double xPos, double yPos,char str[], int stringSize, uint8_t asciiBuff)
{
bitmapLetter fnt_controller(0,0,0x00,0,0);
bitmapLetter sheldon_alph[0x5A];
fnt_controller.createDictionary(sheldon_alph,6,8);
int startX = xPos;
int startY = yPos;
for (int i=0; i < stringSize; i++){
char charAt = str[i];
uint8_t ascii = (uint8_t)charAt;
if (ascii > 0x60)
{
charAt = charAt & ~(0x20);
ascii = ascii & ~(0x20);
}
int width = sheldon_alph[ascii-asciiBuff].getWidth();
int height = sheldon_alph[ascii-asciiBuff].getHeight();
size_t siz = sheldon_alph[ascii-asciiBuff].getSize();
unsigned char* bitmap = sheldon_alph[ascii-asciiBuff].getLetter();
drawBitmap(startX,startY,width,height,bitmap,siz);
startX = startX - 8;
if (startX <= 0)
{
startX = xPos;
startY = startY+8;
}
}
}
and my main loop looks something like this
Music music("", "", "", "", false, 0);
RideTracking ride("", "", "", "", "", false);
Navigation nav("", "", "", "", "", false);
void loop(){
if (bt.getDataUpdated() == false)
{
bt.recvWithEndMarker(&bt,&music);
}
else
{
//Serial.println(music.getTrack());
musicUpdateTrack(music.getTrack());
//Serial.println(music.getArtist()); --> This returns gibberish. If the above update is commented out, it works.
musicUpdateArtist(music.getArtist());
bt.setDataUpdated(false);
}
}
Ive tried everything i can think of, which was a lot of messing around with pointers and addresses to see if it was allocated correctly. This is the closest ive gotten, but it seems like the drawText breaks the rest of the char pointers i call in the future. I dont believe the issue has to do with flash or SRAM, as both seem to be within normal values. Any help would be greatly appreciated.
EDIT: in my bluetooth object, there are two calls. one is receive the data, and the other updates the object. I originally didnt include this as it looks like data is set correctly. if i dont call drawtext, but just call print statements, the data is correct.
void blue::updateData(Music* music) {
if (getDataUpdated() == true) {
StaticJsonDocument<256> doc;
DeserializationError error = deserializeJson(doc, receivedChars);
else{
char s1[55];
char s2[55];
char s3[15];
char s4[15];
char s5[15];
if(doc["music"]) {
strlcpy(s1, doc["music"]["track"]);
music->setTrack(s1);
strlcpy(s2, doc["music"]["artist"]);
music->setArtist(s2);
strlcpy(s3, doc["music"]["track_length"]);
music->setLength(s3);
strlcpy(s4, doc["music"]["position"]);
music->setPosition(s4);
music->setProgressBar(doc["music"]["progressBar"]);
music->setPlaying(doc["music"]["playing"]);
}
}
void blue::recvWithEndMarker(blue* bt,Music* mu) {
char rc;
while (ble.available() > 0 && getDataUpdated() == false) {
rc = ble.read();;
if (rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars)
{
ndx = numChars - 1;
}
}
else
{
brackets++;
if(brackets != 2)
{
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars)
{
ndx = numChars - 1;
}
}
else
{
receivedChars[ndx] = rc;
receivedChars[ndx+1] = '\0'; // terminate the string
ndx = 0;
brackets = 0;
setDataUpdated(true);
}
}
}
bt->updateData(mu);
}

Found it! In the music class, i changed the variables such as *track, to a hardset track[50]. Then, in the set method, i changed it to
void setLength(char * l){
strlcpy(length,l,strlen(l)+1);
}
void setPosition(char *p){
strlcpy(position,p,strlen(p)+1);
}
void setArtist(char *a){
strlcpy(artist,a,strlen(a)+1);
}
void setTrack(char *t){
strlcpy(track,t,strlen(t)+1);
}
Along with a few changes in how its passed, it now works. Thanks! Ive been stuck on this for days.

Related

Private member's malloc memory overwritten after calling another object's (of same class) function

Function called by object output of same class as object input seems to cause unexpected behaviour and overwrite object input's mallocated private member's data (pointer adresses stays same)
For object output both *fileStr and *p_file are NULL and for input both points at data
Both CASE1/CASE2 or combination of each #ifdef will cause input.fileStr data to be changed
input.fileStr data itself is malloc'ated by class1::open if called (called only by input) - else it's a NULL pointer by default
Header
class class1
{
private:
FILE *p_file = NULL;
char *fileStr = NULL;
bool encrypt_step1();
public:
bool open(char *pathto);
bool create(char *pathto);
bool encrypt();
~class1();
};
bool sub_function(char *pathIN);
Source Code
bool class1::open(char *pathto)
{
if (PathFileExistsA(pathto))
this->p_file = fopen(pathto, "rb+");
else
return 0;
if (!(this->p_file))
{
printf("Can't open\n");
return 0;
}
fseek(p_file, 0, SEEK_END);
long filesize = ftell(p_file);
fseek(p_file, 0, SEEK_SET);
this->fileStr = (char*)malloc(filesize+1);
this->fileStr[(fread(this->fileStr, 1, filesize, this->p_file))] = '\0';
return 1;
}
bool class1::create(char *pathto)
{
#ifdef CASE1
if (PathFileExistsA(pathto))
{
char pathtobak[MAX_PATH];
strcpy(pathtobak, pathto);
strcat(pathtobak, ".bak");
int i = 0;
char a[11];
if (PathFileExistsA(pathtobak))
{
while (1)
{
i++;
*a = '\0';
itoa(i, a, 10);
char *reset = pathtobak + strlen(pathtobak);
strcat(pathtobak, a);
if (!PathFileExistsA(pathtobak))
break;
*reset = '\0';
}
}
std::experimental::filesystem::copy_file(pathto, pathtobak);
}
#endif
#ifdef CASE2
this->p_file = fopen(pathto, "wb");
#endif
#ifndef NOERRORS
if (this->p_file == NULL)
return 0;
else
return 1;
#endif
}
class1::~class1()
{
if (this->fileStr)
{
free(this->fileStr);
this->fileStr = NULL;
}
if (this->p_file)
{
fclose(this->p_file);
this->p_file = NULL;
}
}
bool sub_function(char *pathIN)
{
class1 input;
input.open(pathIN);
input.encrypt();//omitted since this should be irrelevant
char pathOUT[MAX_PATH];
strcpy(pathOUT, pathIN);
char *OUText = pathOUT;
OUText += (strlen(pathOUT)-3);
*OUText = '\0';
strcat(pathOUT, "ext");
class1 output;
output.create(pathOUT);//bug here
char *next = input.get_fileStr();
...
}
It seems like memory access violation, but even CASE1 that's simple look up for duplicate files with only use of local variable still causes unexpected behaviour, so I have issues pinpointing the cause
Memory seems to be already released
Most plausible cause would be memory being marked as free, but I don't deallocate it outside of destructor, but when running program further once destructor of input has been called free(input.fileStr) will crash with is_block_type_valid(header->_block_use) exception
Actual issue with working example
Source Code starting from sub_function::input.encrypt()
bool class1::encrypt_step1()
{
bool *strBOOL_11_00 = (bool*)malloc(((strlen(this->fileStr)) + 1) * ((sizeof(bool)) * 8));
bool *strBOOL_10_01 = (bool*)malloc(((strlen(this->fileStr)) + 1) * ((sizeof(bool)) * 8));
bool *strBOOL_10_11 = (bool*)malloc(((strlen(this->fileStr)) + 1) * ((sizeof(bool)) * 8));
char *fileStrIt = this->fileStr;
char *fileStrIt2 = ((this->fileStr) + 1);
bool *next1100 = strBOOL_11_00;
bool *next1001 = strBOOL_10_01;
bool *next1011 = strBOOL_10_11;
//translating to binary array iterating through pointers above one by one happens here
//char->bin/encrypt/bin->char
//ommited
//reallocation to fit new encrypted and translated back to char that caused issues
#ifdef ISSUE
char *fileStr_temp = (char *)realloc(this->fileStr, ((next1011 - strBOOL_10_11) + (next1001 - strBOOL_10_01) + (next1100 - strBOOL_11_00) + 1));
if (!fileStr_temp)
return 0;
//original fileStr points at freed memory
#endif
#ifdef CORRECT
char *fileStr_temp = (char *)realloc(this->fileStr, ((next1011 - strBOOL_10_11) + (next1001 - strBOOL_10_01) + (next1100 - strBOOL_11_00) + 1));
if (!fileStr_temp)
return 0;
else
this->fileStr = fileStr_temp;//original fileStr points at new adress with reallocated data
#endif
free(strBOOL_11_00);
strBOOL_11_00 = NULL;
free(strBOOL_10_01);
strBOOL_10_01 = NULL;
free(strBOOL_10_11);
strBOOL_10_11 = NULL;
return 1;
}
bool class1::encrypt()
{
encrypt_step1();
...//other steps (irrelevant)
return 1;
}

C++ linked list has junk nodes appearing in it [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
When implementing a call stack trace for tracking allocation in my overridden new function, I am using ::malloc to create an untracked call stack object that is then put into a linked list. When my harness finishes new-ing off all of the test cases, the list is sound. However, when i go to report the list (print to console) there are now values that should not be there and are causing it to crash. Below is the simplified version (I apologize that even simplified it is still a lot of code), I am hoping someone can make since of this:
Macros
#define convertToKiB(size) size * 1024UL
#define convertToMiB(size) size * (1024UL * 1024UL)
#define convertToGiB(size) size * (1024UL * 1024UL * 1024UL)
#define convertToReadableBytes(size) ((uint32_t)size > convertToKiB(2) && (uint32_t)size < convertToMiB(2)) ? (float)size / (float)convertToKiB(1) : ((uint32_t)size > convertToMiB(2) && (uint32_t)size < convertToGiB(2)) ? (float)size / (float)convertToMiB(1) : ((uint32_t)size > convertToGiB(2)) ? (float)size / (float)convertToMiB(1) : (float)size
#define convertToReadableBytesString(size) ((uint32_t)size > convertToKiB(2) && (uint32_t)size < convertToMiB(2)) ? "KiB" : ((uint32_t)size > convertToMiB(2) && (uint32_t)size < convertToGiB(2)) ? "MiB" : ((uint32_t)size > convertToGiB(2)) ? "GiB" : "B"
Globals
const uint8_t MAX_FRAMES_PER_CALLSTACK = 128;
const uint16_t MAX_SYMBOL_NAME_LENGTH = 128;
const uint32_t MAX_FILENAME_LENGTH = 1024;
const uint16_t MAX_DEPTH = 128;
typedef BOOL(__stdcall *sym_initialize_t)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);
typedef BOOL(__stdcall *sym_cleanup_t)(IN HANDLE hProcess);
typedef BOOL(__stdcall *sym_from_addr_t)(IN HANDLE hProcess, IN DWORD64 Address, OUT PDWORD64 Displacement, OUT PSYMBOL_INFO Symbol);
typedef BOOL(__stdcall *sym_get_line_t)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Symbol);
static HMODULE g_debug_help;
static HANDLE g_process;
static SYMBOL_INFO* g_symbol;
static sym_initialize_t g_sym_initialize;
static sym_cleanup_t g_sym_cleanup;
static sym_from_addr_t g_sym_from_addr;
static sym_get_line_t g_sym_get_line_from_addr_64;
static int g_callstack_count = 0;
static callstack_list* g_callstack_root = nullptr;
CallStack Object
struct callstack_line_t
{
char file_name[128];
char function_name[256];
uint32_t line;
uint32_t offset;
};
class CallStack
{
public:
CallStack();
uint32_t m_hash;
uint8_t m_frame_count;
void* m_frames[MAX_FRAMES_PER_CALLSTACK];
};
CallStack::CallStack()
: m_hash(0)
, m_frame_count(0) {}
bool CallstackSystemInit()
{
// Load the dll, similar to OpenGL function fecthing.
// This is where these functions will come from.
g_debug_help = LoadLibraryA("dbghelp.dll");
if (g_debug_help == nullptr) {
return false;
}
// Get pointers to the functions we want from the loded library.
g_sym_initialize = (sym_initialize_t)GetProcAddress(g_debug_help, "SymInitialize");
g_sym_cleanup = (sym_cleanup_t)GetProcAddress(g_debug_help, "SymCleanup");
g_sym_from_addr = (sym_from_addr_t)GetProcAddress(g_debug_help, "SymFromAddr");
g_sym_get_line_from_addr_64 = (sym_get_line_t)GetProcAddress(g_debug_help, "SymGetLineFromAddr64");
// Initialize the system using the current process [see MSDN for details]
g_process = ::GetCurrentProcess();
g_sym_initialize(g_process, NULL, TRUE);
// Preallocate some memory for loading symbol information.
g_symbol = (SYMBOL_INFO *) ::malloc(sizeof(SYMBOL_INFO) + (MAX_FILENAME_LENGTH * sizeof(char)));
g_symbol->MaxNameLen = MAX_FILENAME_LENGTH;
g_symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
return true;
}
void CallstackSystemDeinit()
{
// cleanup after ourselves
::free(g_symbol);
g_symbol = nullptr;
g_sym_cleanup(g_process);
FreeLibrary(g_debug_help);
g_debug_help = NULL;
}
// Can not be static - called when
// the callstack is freed.
void DestroyCallstack(CallStack *ptr)
{
::free(ptr);
}
CallStack* CreateCallstack(uint8_t skip_frames)
{
// Capture the callstack frames - uses a windows call
void *stack[MAX_DEPTH];
DWORD hash;
// skip_frames: number of frames to skip [starting at the top - so don't return the frames for "CreateCallstack" (+1), plus "skip_frame_" layers.
// max_frames to return
// memory to put this information into.
// out pointer to back trace hash.
uint32_t frames = CaptureStackBackTrace(1 + skip_frames, MAX_DEPTH, stack, &hash);
// create the callstack using an untracked allocation
CallStack *cs = (CallStack*) ::malloc(sizeof(CallStack));
// force call the constructor (new in-place)
cs = new (cs) CallStack();
// copy the frames to our callstack object
unsigned int frame_count = min(MAX_FRAMES_PER_CALLSTACK, frames);
cs->m_frame_count = frame_count;
::memcpy(cs->m_frames, stack, sizeof(void*) * frame_count);
cs->m_hash = hash;
return cs;
}
//------------------------------------------------------------------------
// Fills lines with human readable data for the given callstack
// Fills from top to bottom (top being most recently called, with each next one being the calling function of the previous)
//
// Additional features you can add;
// [ ] If a file exists in yoru src directory, clip the filename
// [ ] Be able to specify a list of function names which will cause this trace to stop.
uint16_t CallstackGetLines(callstack_line_t *line_buffer, const uint16_t max_lines, CallStack *cs)
{
IMAGEHLP_LINE64 line_info;
DWORD line_offset = 0; // Displacement from the beginning of the line
line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
unsigned int count = min(max_lines, cs->m_frame_count);
unsigned int idx = 0;
for (unsigned int i = 0; i < count; ++i) {
callstack_line_t *line = &(line_buffer[idx]);
DWORD64 ptr = (DWORD64)(cs->m_frames[i]);
if (FALSE == g_sym_from_addr(g_process, ptr, 0, g_symbol)) {
continue;
}
strcpy_s(line->function_name, 256, g_symbol->Name);
BOOL bRet = g_sym_get_line_from_addr_64(
GetCurrentProcess(), // Process handle of the current process
ptr, // Address
&line_offset, // Displacement will be stored here by the function
&line_info); // File name / line information will be stored here
if (bRet)
{
line->line = line_info.LineNumber;
strcpy_s(line->file_name, 128, line_info.FileName);
line->offset = line_offset;
}
else {
// no information
line->line = 0;
line->offset = 0;
strcpy_s(line->file_name, 128, "N/A");
}
++idx;
}
return idx;
}
Operators
// Treat as Linked List Node
struct callstack_list
{
CallStack* current_stack = nullptr;
uint16_t total_allocation = 0;
callstack_list* next = nullptr;
};
struct allocation_meta
{
uint16_t size;
callstack_list callstack_node;
};
void* operator new(const size_t size)
{
uint16_t alloc_size = (uint16_t)size + (uint16_t)sizeof(allocation_meta);
allocation_meta *ptr = (allocation_meta*)::malloc((size_t)alloc_size);
ptr->size = (uint16_t)size;
ptr->callstack_node.current_stack = CreateCallstack(0);
ptr->callstack_node.total_allocation = (uint16_t)size;
ptr->callstack_node.next = nullptr;
bool run = true;
callstack_list* currentNode = nullptr;
while (g_callstack_root != nullptr && run)
{
if (currentNode == nullptr)
{
currentNode = g_callstack_root;
}
if (currentNode->next != nullptr)
{
currentNode = currentNode->next;
}
else
{
currentNode->next = &ptr->callstack_node;
run = false;
}
}
if (g_callstack_root == nullptr)
{
g_callstack_root = &ptr->callstack_node;
}
return ptr + 1;
}
void operator delete(void* ptr)
{
if (nullptr == ptr)
return;
allocation_meta *data = (allocation_meta*)ptr;
data--;
if (data->callstack_node.current_stack != nullptr)
DestroyCallstack(data->callstack_node.current_stack);
bool run = true;
callstack_list* currentNode = nullptr;
while (g_callstack_root != nullptr && run && &data->callstack_node != NULL)
{
if (currentNode == nullptr && g_callstack_root != &data->callstack_node)
{
currentNode = g_callstack_root;
}
else
{
g_callstack_root = nullptr;
run = false;
continue;
}
if (currentNode->next != nullptr && currentNode->next != &data->callstack_node)
{
currentNode = currentNode->next;
}
else
{
currentNode->next = nullptr;
run = false;
}
}
::free(data);
}
Test Harness
void ReportVerboseCallStacks(const char* start_time_str = "", const char* end_time_str = "")
{
callstack_list* currentNode = g_callstack_root;
unsigned int totalSimiliarAllocs = 0;
uint32_t totalSimiliarSize = 0;
while (currentNode != nullptr)
{
callstack_list* nextNode = currentNode->next;
uint32_t& currentHash = currentNode->current_stack->m_hash;
uint32_t nextHash;
if (nextNode == nullptr)
nextHash = currentHash + 1;
else
nextHash = nextNode->current_stack->m_hash;
if (nextHash == currentHash)
{
totalSimiliarSize += currentNode->total_allocation;
totalSimiliarAllocs++;
}
if (nextHash != currentHash)
{
//Print total allocs for type and total size
float reportedBytes = convertToReadableBytes(totalSimiliarSize);
std::string size = convertToReadableBytesString(totalSimiliarSize);
char collection_buffer[128];
sprintf_s(collection_buffer, 128, "\nGroup contained %s allocation(s), Total: %0.3f %s\n", std::to_string(totalSimiliarAllocs).c_str(), reportedBytes, size.c_str());
printf(collection_buffer);
//Reset total allocs and size
totalSimiliarAllocs = 0;
totalSimiliarSize = 0;
}
// Printing a call stack, happens when making report
char line_buffer[512];
callstack_line_t lines[128];
unsigned int line_count = CallstackGetLines(lines, 128, currentNode->current_stack);
for (unsigned int i = 0; i < line_count; ++i)
{
// this specific format will make it double click-able in an output window
// taking you to the offending line.
//Print Line For Call Stack
sprintf_s(line_buffer, 512, " %s(%u): %s\n", lines[i].file_name, lines[i].line, lines[i].function_name);
printf(line_buffer);
}
currentNode = currentNode->next;
}
}
void Pop64List(int64_t* arr[], int size)
{
for (int index = 0; index < size; ++index)
{
arr[index] = new int64_t;
*arr[index] = (int64_t)index;
}
}
void Pop8List(int8_t* arr[], int size)
{
for (int index = 0; index < size; ++index)
{
arr[index] = new int8_t;
*arr[index] = (int8_t)index;
}
}
int main()
{
if (!CallstackSystemInit())
return 1;
const int SIZE_64 = 8000;
int64_t* arr_64[SIZE_64];
const int SIZE_8 = 10000;
int8_t* arr_8[SIZE_8];
Pop64List(arr_64, SIZE_64);
Pop8List(arr_8, SIZE_8);
ReportVerboseCallStacks();
CallstackSystemDeinit();
return 0;
}
I finally figured out the answer. In my reporting function I was using std::string to create some of the reporting objects. std::string calls ::new internally to create a small allocation, and then hammers additional memory as the string's internal array reallocates memory. Switching to C-strings solved my problem.

Convert mixed JSON-Number-Array to int, uint, float using lib rapidjson

As I understood this char* is a valid json-string.
const char* json = { "array":[14, -15, 3.17], "array_type": ["uint", "int", "float"] }
All numbers in the array shall be 4 bytes.
How could one loop through the array using rapidjson?
This is my code so far:
#include "rapidjson/document.h"
using namespace rapidjson;
int main(void)
{
int i_val; unsigned int ui_val; float f_val;
const char* json = "{ \"array\":[14, -15, 3.17], \"array_type\" : [\"uint\", \"int\", \"float\"] }";
Document d;
d.Parse<0>(json);
Value& a = d["array"];
Value& at = d["array_type"];
for (SizeType i = 0; i<a.Size(); i++)
{
if (a[i].IsInt() && (std::string)at[i].GetString() == "int")
{
i_val = a[i].GetInt();
//Do anything
}
if (a[i].IsUint() && (std::string)at[i].GetString() == "uint")
{
ui_val = a[i].GetUint();
//Do anything
}
if (a[i].IsDouble() && (std::string)at[i].GetString() == "float")
{
f_val = (float)a[i].GetDouble();
//Do anything
}
}//end for
return 0;
}
ERROR:
TestApp: /workspace/TestApp/src/include/rapidjson/document.h:1277: rapidjson::GenericValue<Encoding, Allocator>& rapidjson::GenericValue<Encoding, Allocator>::operator[](rapidjson::SizeType) [with Encoding = rapidjson::UTF8<>; Allocator = rapidjson::MemoryPoolAllocator<>; rapidjson::SizeType = unsigned int]: Assertion `index < data_.a.size' failed.
The code crashes at the function a.Size(), when it is executed after GetDouble. How could one solve this?
I know the last "if" is wrong and thats probably why the program crashes. Double is 8 bytes and the SizeType is 4 bytes by default.
Is there a solution to loop though the array?? If not I also would be good with other libs.. I need to transport these three different types of values by json. By the way the length of the array could be 1 to 500.
(There is no GetFloat() function.)
Thanks for any kind of help.
Regards
You can use JSONLint to validate json string.
Your example fixed:
int i_val; unsigned int ui_val; float f_val;
const char* json = "{ \"array\":[14, -15, 3.17], \"array_type\" : [\"uint\", \"int\", \"float\"] }";
rapidjson::Document d;
d.Parse<0>(json);
rapidjson::Value& a = d["array"];
rapidjson::Value& at = d["array_type"];
for (rapidjson::SizeType i = 0; i<a.Size(); i++)
{
if (a[i].IsInt() && (std::string)at[i].GetString() == "int")
{
i_val = a[i].GetInt();
//Do anything
}
if (a[i].IsUint() && (std::string)at[i].GetString() == "uint")
{
ui_val = a[i].GetUint();
//Do anything
}
if (a[i].IsDouble() && (std::string)at[i].GetString() == "float")
{
f_val = (float)a[i].GetDouble();
//Do anything
}
}

Can't return anything other than 1 or 0 from int function

I wish my first post wasn't so newbie. I've been working with openframeworks, so far so good, but as I'm new to programming I'm having a real headache returning the right value from an int function. I would like the int to increment up until the Boolean condition is met and then decrement to zero. The int is used to move through an array from beginning to end and then back. When I put the guts of the function into the method that I'm using the int in, everything works perfectly, but very messy and I wonder how computationally expensive it is to put there, it just seems that my syntactic abilities are lacking to do otherwise. Advice appreciated, and thanks in advance.
int testApp::updown(int j){
if(j==0){
arp =true;
}
else if (j==7){
arp = false;
}
if(arp == true){
j++;
}
else if(arp == false){
j--;
}
return (j);
}
and then its called like this in an audioRequest block of the library I'm working with:
for (int i = 0; i < bufferSize; i++){
if ((int)timer.phasor(sorSpeed)) {
z = updown(_j);
noteOut = notes [z];
cout<<arp;
cout<<z;
}
EDIT: For addition of some information. Removed the last condition of the second if statement, it was there because I was experiencing strange happenings where j would start walking off the end of the array.
Excerpt of testApp.h
int z, _j=0;
Boolean arp;
EDIT 2: I've revised this now, it works, apologies for asking something so rudimentary and with such terrible code to go with. I do appreciate the time that people have taken to comment here. Here are my revised .cpp and my .h files for your perusal. Thanks again.
#include "testApp.h"
#include <iostream>
using namespace std;
testApp::~testApp() {
}
void testApp::setup(){
sampleRate = 44100;
initialBufferSize = 1024;
//MidiIn.openPort();
//ofAddListener(MidiIn.newMessageEvent, this, &testApp::newMessage);
j = 0;
z= 0;
state = 1;
tuning = 440;
inputNote = 127;
octave = 4;
sorSpeed = 2;
freqOut = (tuning/32) * pow(2,(inputNote-69)/12);
finalOut = freqOut * octave;
notes[7] = finalOut+640;
notes[6] = finalOut+320;
notes[5] = finalOut+160;
notes[4] = finalOut+840;
notes[3] = finalOut+160;
notes[2] = finalOut+500;
notes[1] = finalOut+240;
notes[0] = finalOut;
ofSoundStreamSetup(2,0,this, sampleRate, initialBufferSize, 4);/* Call this last ! */
}
void testApp::update(){
}
void testApp::draw(){
}
int testApp::updown(int &_j){
int tmp;
if(_j==0){
arp = true;
}
else if(_j==7) {
arp = false;
}
if(arp == true){
_j++;
}
else if(arp == false){
_j--;
}
tmp = _j;
return (tmp);
}
void testApp::audioRequested (float * output, int bufferSize, int nChannels){
for (int i = 0; i < bufferSize; i++){
if ((int)timer.phasor(sorSpeed)) {
noteOut = notes [updown(z)];
}
mymix.stereo(mySine.sinewave(noteOut),outputs,0.5);
output[i*nChannels ] = outputs[0];
output[i*nChannels + 1] = outputs[1];
}
}
testApp.h
class testApp : public ofBaseApp{
public:
~testApp();/* destructor is very useful */
void setup();
void update();
void draw();
void keyPressed (int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
void newMessage(ofxMidiEventArgs &args);
ofxMidiIn MidiIn;
void audioRequested (float * input, int bufferSize, int nChannels); /* output method */
void audioReceived (float * input, int bufferSize, int nChannels); /* input method */
Boolean arp;
int initialBufferSize; /* buffer size */
int sampleRate;
int updown(int &intVar);
/* stick you maximilian stuff below */
double filtered,sample,outputs[2];
maxiFilter filter1;
ofxMaxiMix mymix;
ofxMaxiOsc sine1;
ofxMaxiSample beats,beat;
ofxMaxiOsc mySine,myOtherSine,timer;
int currentCount,lastCount,i,j,z,octave,sorSpeed,state;
double notes[8];
double noteOut,freqOut,tuning,finalOut,inputNote;
};
It's pretty hard to piece this all together. I do think you need to go back to basics a bit, but all the same I think I can explain what is going on.
You initialise _j to 0 and then never modify the value of _j.
You therefore call updown passing 0 as the parameter every time.
updown returns a value of 1 when the input is 0.
Perhaps you meant to pass z to updown when you call it, but I cannot be sure.
Are you really declaring global variables in your header file? That's not good. Try to use local variables and/or parameters as much as possible. Global variables are pretty evil, especially declared in the header file like that!

strlen() not working

Basically, I'm passing a pointer to a character string into my constructor, which in turn initializes its base constructor when passing the string value in. For some reason strlen() is not working, so it does not go into the right if statement. I have checked to make sure that there is a value in the variable and there is.
Here is my code, I've taken out all the irrelevant parts:
Label class contents:
Label(int row, int column, const char *s, int length = 0) : LField(row, column, length, s, false)
{
}
Label (const Label &obj) : LField(obj)\
{
}
~Label()
{
}
Field *clone() const
{
return new Label(*this);
}
LField class contents:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = "", bool canEditVal = true)
{
if(strlen(valVal) > 0)
{
}
else
{
//This is where it jumps to, even though the value in
//valVal is 'SFields:'
val = NULL;
}
}
Field *clone() const
{
return new LField(*this);
}
LField(const LField &clone) {
delete[] val;
val = new char[strlen(clone.val) + 1];
strcpy(val, clone.val);
rowNum = clone.rowNum;
colNum = clone.colNum;
width = clone.width;
canEdit = clone.canEdit;
index = clone.index;
}
Screen class contents:
class Screen {
Field *fields[50];
int numOfFields;
int currentField;
public:
Screen()
{
numOfFields = 0;
currentField = 0;
for(int i = 0; i < 50; i++)
fields[i] = NULL;
}
~Screen()
{
for (int i = 0; i < 50; i++)
delete[] fields[i];
}
int add(const Field &obj)
{
int returnVal = 0;
if (currentField < 50)
{
delete[] fields[currentField];
fields[currentField] = obj.clone();
numOfFields += 1;
currentField += 1;
returnVal = numOfFields;
}
return returnVal;
}
Screen& operator+=(const Field &obj)
{
int temp = 0;
temp = add(obj);
return *this;
}
};
Main:
int main () {
Screen s1;
s1 += Label(3, 3, "SFields:");
}
Hopefully someone is able to see if I am doing something wrong.
<LANGUAGE FEATURE XXXX IS BROKEN>! ... No, it isn't.
Just before measuring the string, write in a puts(valVal), to ensure you are not mistaken about the contents of that variable.
Marcin at this point the problem will come down to debugging, I copied your code with some minor omissions and got the correct result.
Now it needs to be said, you should be using more C++ idiomatic code. For instance you should be using std::string instead of const char* and std::vector instead of your raw arrays.
Here is an example of what the LField constructor would look like with std::string:
#include <string> // header for string
LField(int rowNumVal,
int colNumVal,
int widthVal,
const std::string& valVal = "",
bool canEditVal = true)
{
std::cout << valVal;
if(valVal.length() > 0)
{
}
else
{
//This is where it jumps to, even though the value in
//valVal is 'SFields:'
//val = NULL;
}
}
Using these types will make your life considerably easier and if you make the change it may just fix your problem too.
PREVIOUS:
So you can be CERTAIN that the string is not being passed in correctly add a printline just before the strlen call. Once you do this work backward with printlines until you find where the string is not being set. This is a basic debugging technique.
Label(int row,
int column,
const char *s,
int length = 0) :
LField(row, column, length, s, false) {
}
LField(int rowNumVal,
int colNumVal,
int widthVal,
const char *valVal = "",
bool canEditVal = true)
{
std::cout << valVal << std::endl;
if(strlen(valVal) > 0)
{
}
else {
//This is where it jumps to, even though the value in
//valVal is 'SFields:'
val = NULL;
}
}
Whenever there is strange behavior like this, memory getting screwed up is almost always the culprit. Never mix new with delete[] OR new[] with delete. The latter is slightly worse than the former but they are both bad news. delete[] should only be used in conjunction with new[]. Mixing these allocation/deallocation notations will result in undefined behavior. Since you are never using new[], replace all of your delete[] calls with delete. It is also good practice and good manners to set your pointers to NULL after you delete them. It is highly unlikely that you will be the only one debugging this code and it would be extremely annoying to debug your pointers thinking that there is valid memory there, when in fact there isn't.
Mixing these notations inevitably lead to exploits and memory leaks.
There is a problem here:
LField(const LField &clone) {
delete[] val;
val = new char[strlen(clone.val) + 1];
val is uninitialized when the constructor is called, and you are deleting it.