I'm trying forward declare my functions in a namespace. But I get an error.
Let me show my .h and .cpp files first.
Header:
namespace DeviceList
{
int GetIDFromType(NNBSSString type);
NNBSSString GetTypeFromID(int id);
void CNNBSSDeviceListAddDevice(NNBSSString& DeviceName, NNBSSString& Address, int DeviceType,
__STRING__ DeviceNetName, __STRING__ DevicePath);
void CNNBSSDeviceListRemoveSelected();
void CNNBSSDeviceListRemoveCache(int index);
inline void CNNBSSDeviceListAddressConnectionRespond(NNBSSString& deviceAddress, bool OK, NNBSSThread* thread);
void CNNBSSDeviceListUpdate();
}
And Source file:
namespace DeviceList
{
int GetIDFromType(NNBSSString type)
{
int m_id;
if (type == _("USB Camera"))
{
m_id = NNBSS_EVT_DEVICETYPE_USBCAM;
}
else if (type == _("IP Camera"))
{
m_id = NNBSS_EVT_DEVICETYPE_IPCAM;
}
else if (type == _("Microphone"))
{
m_id = NNBSS_EVT_DEVICETYPE_MICROPHONE;
}
else if (type == _("DVR"))
{
m_id = NNBSS_EVT_DEVICETYPE_DVR;
}
else if (type == _("NVR"))
{
m_id = NNBSS_EVT_DEVICETYPE_NVR;
}
else
{
m_id = -100;
NNBSSErrorShow("Given DeviceType was wrong while getting int from NNBSSString!", 100);
}
return m_id;
}
NNBSSString GetTypeFromID(int id)
{
// Has to be given by using GetIDFromEnum
NNBSSString m_type;
switch (id)
{
case NNBSS_EVT_DEVICETYPE_USBCAM:
m_type = _("USB Camera");
break;
case NNBSS_EVT_DEVICETYPE_IPCAM:
m_type = _("IP Camera");
break;
case NNBSS_EVT_DEVICETYPE_MICROPHONE:
m_type = _("Microphone");
break;
case NNBSS_EVT_DEVICETYPE_DVR:
m_type = _("DVR");
break;
case NNBSS_EVT_DEVICETYPE_NVR:
m_type = _("NVR");
break;
default:
NNBSSErrorShow("Given DeviceType was wrong while getting NNBSSString from int!", 100);
break;
}
return m_type;
}
void CNNBSSDeviceListAddDevice(NNBSSString& DeviceName, NNBSSString& Address, int DeviceType,
__STRING__ DeviceNetName = __STRING__(), __STRING__ DevicePath = __STRING__())
{
SCNNBSSDeviceParameters params;
params.DeviceName = DeviceName;
params.Address = Address;
params.DeviceType = DeviceType;
params.DeviceNetName = DeviceNetName;
params.DevicePath = DevicePath;
SCNNBSSDeviceParametersList.emplace_back(params);
{
CNNBSSHardwareCheckCameraConnection* p_CNNBSSHardwareCheckCameraConnection =
new CNNBSSHardwareCheckCameraConnection(Address);
p_CNNBSSHardwareCheckCameraConnection->Run();
}
// Update all pages that have Device List active
for (int c = 0; c < (int)m_NNBSSContentPanelList.size(); c++)
{
int pageID = c - 1;
pageID < 0 ? pageID = 0 : pageID = c - 1;
if (CNNBSSDeviceListAddressHandle(m_NNBSSContentPanelList[c])->_IsCreated)
{
CNNBSSDeviceListAddressHandle(m_NNBSSContentPanelList[c])->_RecreateList();
}
}
}
void CNNBSSDeviceListRemoveSelected()
{
if (CNNBSSDeviceListAddressHandle(CNNBSSControlPanelAddressHandle()->_GetCurrentContentPanel())->_IsCreated)
{
CNNBSSDeviceListAddressHandle(CNNBSSControlPanelAddressHandle()->_GetCurrentContentPanel())
->_RemoveSelectedFromList();
}
// Update all pages that have Device List active
for (int c = 0; c < (int)m_NNBSSContentPanelList.size(); c++) {
int pageID = c - 1;
pageID < 0 ? pageID = 0 : pageID = c - 1;
if (CNNBSSDeviceListAddressHandle(m_NNBSSContentPanelList[c])->_IsCreated)
{
CNNBSSDeviceListAddressHandle(m_NNBSSContentPanelList[c])->_RecreateList();
}
}
}
void CNNBSSDeviceListRemoveCache(int index)
{
if (index < 0)
{
index = 0;
}
if (SCNNBSSDeviceParametersList.size() < index)
{
index = (int)SCNNBSSDeviceParametersList.size();
}
auto itr = SCNNBSSDeviceParametersList.begin();
std::advance(itr, index);
if (itr != SCNNBSSDeviceParametersList.end())
{
SCNNBSSDeviceParametersList.erase(itr);
}
}
void CNNBSSDeviceListAddressConnectionRespond(NNBSSString& deviceAddress, bool OK, wxThread* thread)
{
for (int c = 0; c < (int)SCNNBSSDeviceParametersList.size(); c++)
{
if (SCNNBSSDeviceParametersList[c].Address == deviceAddress)
{
if (OK)
{
SCNNBSSDeviceParametersList[c].DeviceConnectionStatus = NNBSS_DEVICE_CONNECTION_STATUS_STRING_ONLINE;
}
else
{
SCNNBSSDeviceParametersList[c].DeviceConnectionStatus = NNBSS_DEVICE_CONNECTION_STATUS_STRING_UNKNOWNERROR;
}
break;
}
}
// Update all pages that have Device List active
for (int c = 0; c < (int)m_NNBSSContentPanelList.size(); c++)
{
int pageID = c - 1;
pageID < 0 ? pageID = 0 : pageID = c - 1;
if (CNNBSSDeviceListAddressHandle(m_NNBSSContentPanelList[c])->_IsCreated)
{
CNNBSSDeviceListAddressHandle(m_NNBSSContentPanelList[c])->_RecreateList();
}
}
// Delete thread
thread->Delete();
delete thread;
}
void CNNBSSDeviceListUpdate()
{// Whenever a USB device is connected, this function will be called automatically
{
std::vector<__STRING__> currentDevices, currentDevicePaths;
CNNBSSHardwareAddressHandle()->GetConnectedUSBCameraList(currentDevices, currentDevicePaths);
// Update all pages that have Device List active
for (int c = 0; c < (int)m_NNBSSContentPanelList.size(); c++)
{
int pageID = c - 1;
pageID < 0 ? pageID = 0 : pageID = c - 1;
if (CNNBSSDeviceListAddressHandle(m_NNBSSContentPanelList[c])->_IsCreated)
{
CNNBSSDeviceListAddressHandle(m_NNBSSContentPanelList[c])->_RecreateList();
}
}
}
}
The problem is, when I remove inline keyword before CNNBSSDeviceListAddressConnectionRespond function, compiler throws an error though for others compiler does not do the same. I wonder, why others works without inline but not CNNBSSDeviceListAddressConnectionRespond function?
Additionally, the complete error message:
Severity Code Description Project File Line Suppression State
Error LNK1169 one or more multiply defined symbols found NNBSS NNBSS\Build\Debug\NNBSS.exe 1
Error LNK2005 "void __cdecl DeviceList::CNNBSSDeviceListAddressConnectionRespond(class NNBSSString &,bool,class NNBSSThread *)" (?CNNBSSDeviceListAddressConnectionRespond#DeviceList##YAXAEAVNNBSSString##_NPEAVNNBSSThread###Z) already defined in ClassManager.obj NNBSS NNBSS\Build\Thread.obj 1
I use include guards.
And my header file is included by over 128 files.
If anything's missing here, let me know
It seems you are using VS2019. I had the same problem and as internet says we're not alone. So, it's a bug that will be fixed once you rebuild the project.
Related
I find myself in a difficult situation. I have a program which is supposed to delete any memory that is dynamically allocated, but whenever I try to call the relevant methods, it comes up with a memory heap corruption.
It seems to work when I don't call the methods, but then I've probably caused a ton of memory leaks. Would anyone have any idea what is going on?
The code is below:
CSVFile.h:
#pragma once
class InputPattern;
class OutputPattern;
class CSVFile
{
private:
const int NAME_MAX = 100;
char* name;
char** buffer;
bool loadedFlag;
int patternCount;
InputPattern** inputs;
OutputPattern** outputs;
void setLoadedFlagTrue();
void setLoadedFlagFalse();
public:
CSVFile();
~CSVFile();
CSVFile(const char*);
void setName(const char*);
char* getFilename(char*, int);
bool getLoadedFlag();
int loadFile();
InputPattern* getInputPattern(int);
OutputPattern* getOutputPattern(int);
void addInputPattern(InputPattern*);
void addOutputPattern(OutputPattern*);
void deleteInputPattern();
void deleteOutputPattern();
void printMetaData();
void printPatterns();
void deleteBuffer();
};
CSVFile.cpp:
#include "CSVFile.h"
#include "InputPattern.h"
#include "OutputPattern.h"
#include <stdio.h>
#include <string.h>
void CSVFile::setLoadedFlagTrue()
{
loadedFlag = true;
}
void CSVFile::setLoadedFlagFalse()
{
loadedFlag = false;
}
CSVFile::CSVFile()
{
name = NULL;
buffer = NULL;
inputs = NULL;
outputs = NULL;
patternCount = 0;
inputs = new InputPattern*[10];
outputs = new OutputPattern*[10];
buffer = new char*[4];
int i;
for (i = 0; i < 10; i++)
{
inputs[i] = new InputPattern();
outputs[i] = new OutputPattern();
buffer[i] = new char[NAME_MAX];
}
}
CSVFile::~CSVFile()
{
delete name;
name = NULL;
}
CSVFile::CSVFile(const char * filename)
{
name = NULL;
buffer = NULL;
inputs = NULL;
outputs = NULL;
patternCount = 0;
inputs = new InputPattern*[10];
outputs = new OutputPattern*[10];
int i;
for (i = 0; i < 10; i++)
{
inputs[i] = new InputPattern();
outputs[i] = new OutputPattern();
}
name = new char[NAME_MAX];
strcpy(name, filename);
}
void CSVFile::setName(const char * filename)
{
name = new char[NAME_MAX];
strcpy(name, filename);
}
char* CSVFile::getFilename(char * outBuff, int outBuffSize)
{
outBuff = new char[outBuffSize + 1];
strncpy(outBuff, name, outBuffSize);
return outBuff;
}
bool CSVFile::getLoadedFlag()
{
if (name == NULL)
{
setLoadedFlagFalse();
return loadedFlag;
}
if (patternCount == 10)
setLoadedFlagTrue();
else
setLoadedFlagFalse();
return loadedFlag;
}
int CSVFile::loadFile()
{
FILE* f;
if ((f = fopen(name, "r")) == NULL)
{
printf("File failed to open\n");
return 0;
}
for (patternCount = 0; patternCount < 4; patternCount++)
{
fgets(buffer[patternCount], 100, f);
}
patternCount = 0;
/*ask about input interaction; potentially remove these variables afterwards*/
float tIn, rIn, gIn, bIn, tOut, oOut;
/*might change this to make it more flexible*/
while (patternCount < 10)
{
fscanf(f, "%f,%f,%f,%f,%f,%f", &tIn, &rIn, &gIn, &bIn, &tOut, &oOut);
printf("%f,%f,%f,%f,%f,%f\n", tIn, rIn, gIn, bIn, tOut, oOut);
inputs[patternCount]->setT(tIn);
inputs[patternCount]->setR(rIn);
inputs[patternCount]->setG(gIn);
inputs[patternCount]->setB(bIn);
outputs[patternCount]->setT(tOut);
outputs[patternCount]->setO(oOut);
patternCount++;
}
fclose(f);
return patternCount;
}
InputPattern * CSVFile::getInputPattern(int index)
{
if (index >= 0 && index < 10)
return inputs[index];
else
return 0;
}
OutputPattern * CSVFile::getOutputPattern(int index)
{
if (index >= 0 && index < 10)
return outputs[index];
else
return 0;
}
void CSVFile::addInputPattern(InputPattern * in)
{
inputs[patternCount] = in;
patternCount++;
}
void CSVFile::addOutputPattern(OutputPattern * out)
{
outputs[patternCount] = out;
patternCount++;
}
void CSVFile::deleteInputPattern()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete inputs[i];
}
delete inputs;
inputs = NULL;
}
void CSVFile::deleteOutputPattern()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete outputs[i];
}
delete outputs;
outputs = NULL;
}
void CSVFile::printMetaData()
{
int i;
for (i = 0; i < 4; i++)
{
printf("%s", buffer[i]);
}
}
void CSVFile::printPatterns()
{
/*to be completed*/
int i;
for (i = 0; i < patternCount; i++)
{
printf("Class number %d\n", i + 1);
printf("T in = %f\n", inputs[i]->getT());
printf("R in = %f\n", inputs[i]->getR());
printf("G in = %f\n", inputs[i]->getG());
printf("B in = %f\n", inputs[i]->getB());
printf("T out = %f\n", outputs[i]->getT());
printf("O out = %f\n", outputs[i]->getO());
}
}
void CSVFile::deleteBuffer()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete buffer[i];
}
delete buffer;
buffer = NULL;
}
TestHarness.cpp sample (this is executed in the main function)
bool TestHarness::testCSVFileSetFilepath() /*this works fine*/
{
bool testResult = false;
CSVFile* test = NULL;
test = new CSVFile();
char *testName = NULL;
test->setName("test.txt");
testName = test->getFilename(testName, 10);
if (strcmp("test.txt", testName) == 0)
testResult = true;
delete test;
delete testName;
test = NULL;
testName = NULL;
return testResult;
}
...........................
bool TestHarness::testCSVFileLoadFile() /*this causes the corruption*/
{
bool testResult = false;
CSVFile* test = NULL;
test = new CSVFile();
test->setName("C:/Users/user/Documents/AssignmentsSem2/ExampleFile.csv");
if (test->loadFile() == 10)
testResult = true;
test->deleteInputPattern();
test->deleteOutputPattern();
test->deleteBuffer(); /*these three above methods are the ones I'm talking about*/
delete test;
test = NULL;
return testResult;
}
You can check for memory leaks with
#define _CRTDBG_MAP_ALLOC
#include<crtdbg.h>
struct AtExit
{
~AtExit()
{
_CrtDumpMemoryLeaks();
}
}doAtExit;
just outside the main method.
This runs whenever your program ends. All it really does is display whether you have a memory leak or not. Doesn't help with actually finding them.
You might need Visual Studio for this.
This is how it looks when a memory leak is found
I have a struct that looks like this:
// A lexical scope that keeps track of every declared variable
// in a function
struct LexState
{
// A map containing the index of a variable in it's function
// The key is the variable name
std::unordered_map<std::string, int> _vars;
Function *_function;
LexState *_parent;
};
This is the code using the struct:
#define DD(msg) std::cout << "Debug: " << msg << '\n'
#define DD1(msg, p1) std::cout << "Debug: " << msg << p1 << '\n'
#define DD2(msg, p1, p2) std::cout << "Debug: " << msg << p1 << p2 << '\n'
// A lexical scope that keeps track of every declared variable
// in a function
struct LexState
{
// A map containing the index of a variable in it's function
// The key is the variable name
std::unordered_map<std::string, int> _vars;
Function *_function;
LexState *_parent;
LexState(LexState *parent, Function *function)
{
_parent = parent;
_function = function;
}
Value *SearchVar(char *name)
{
if (_parent == nullptr)
{
return nullptr;
}
std::string str(name);
auto var = _parent->_vars.find(str);
if (var == _parent->_vars.end())
{
return _parent->SearchVar(name);
}
return _function->GetLocalVar(var->second)->GetValue();
}
};
class Compiler
{
public:
State *_state;
Function *_current_function;
GC *_gc;
LexState *_ls;
Compiler(State *state) :
_state(state)
{
_current_function = nullptr;
_gc = state->GetGC();
_current_function = new Function(nullptr);
_state->_main_function = _current_function;
_ls = nullptr;
}
void PushFunction()
{
Function *new_function = new Function(_current_function);
_current_function = new_function;
LexState *new_ls = new LexState(_ls, new_function);
// even now, right after creating new_ls, new_ls->_vars is 0
printf("%p\n", &new_ls->_vars);
_ls = new_ls;
}
void PopFunction()
{
_current_function = _current_function->_parent;
LexState *parent = _ls->_parent;
delete _ls;
_ls = parent;
}
int DeclareVar(const Symbol *node)
{
assert(node->_type == NODE_SYMBOL);
DD("Declaring variable");
auto token = node->_token;
char name[token->len + 1];
memcpy(name, token->pos, token->len);
name[token->len] = '\0';
int idx = _current_function->AddLocalVar(name);
std::string key(name);
printf("%p\n", &_ls->_vars);
if (_ls != nullptr)
_ls->_vars.insert(std::make_pair(key, idx));
else
DD("LexState nullptr");
DD("Variable declared");
return idx;
}
void Compile(const Node *node)
{
switch (node->_type)
{
case NODE_CHUNK:
CompileChunk((Chunk *)node);
break;
case NODE_BLOCK:
CompileBlock((Block *)node);
break;
case NODE_FUNCTION_DEF:
CompileFunctionDef((FunctionDef *)node);
break;
case NODE_CONDITIONAL:
CompileConditional((ConditionalStatement *)node);
break;
case NODE_BINARY_EXPR:
CompileBinaryExpr((BinaryExpr *)node);
break;
case NODE_UNARY_EXPR:
CompileUnaryExpr((UnaryExpr *)node);
break;
case NODE_SYMBOL:
CompileSymbol((Symbol *)node);
break;
case NODE_STRING_LITERAL:
CompileStringLiteral((StringLiteral *)node);
break;
case NODE_BOOL_LITERAL:
CompileBoolLiteral((BoolLiteral *)node);
break;
case NODE_INT_LITERAL:
CompileIntLiteral((IntLiteral *)node);
break;
}
}
void CompileChunk(const Chunk *chunk)
{
Compile(chunk->_block);
AddCode(OP_HALT);
}
void CompileBlock(const Block *block)
{
std::vector<Node *> vec = block->_vec;
for (auto it = vec.begin(); it != vec.end(); it++)
{
Compile(*it);
}
}
void CompileFunctionDef(const FunctionDef *func)
{
Value v;
int f = AddConstant(v);
AddCode(OP_PUSH, f);
Value *vp = _current_function->GetConstant(f);
if (func->_name)
{
int fvar = DeclareVar((Symbol *)func->_name);
AddCode(OP_STOR_LOCAL, fvar);
}
ArgList *argsnode = (ArgList *)func->_args;
auto args = argsnode->_vec;
int argcount = args.size();
PushFunction();
auto closure = new Closure(_current_function);
closure->_argcount = argcount;
std::cout << argcount << '\n';
vp->_closure = closure;
vp->_type = VALUE_CLOSURE;
// Compiling inside function
// Arguments are compiled in reserved order, because in the function call
// the passed arguments will be pushed in the order they are passed
for (auto it = args.rbegin(); it != args.rend(); it++)
{
int var = DeclareVar((Symbol *)*it);
AddCode(OP_STOR_LOCAL, var);
}
if (func->_guard)
{
Compile(func->_guard);
}
else
{
Compile(func->_body);
}
AddCode(OP_RETURN);
// End function
PopFunction();
}
void CompileConditional(const ConditionalStatement *node)
{
auto function = _current_function;
Compile(node->_condition);
int cond_res_idx = function->AddLocalVar();
AddCode(OP_DUP);
// Store the condition result into an internal variable
AddCode(OP_STOR_LOCAL, cond_res_idx);
AddCode(OP_DUP);
int true_jmp = AddCode(OP_JMP_T, 0);
int false_jmp = AddCode(OP_JMP_F, 0);
// Save index of the first code of the block
int block_idx = function->_code.size();
// Jump to block when condition is true
function->ChangeCode(true_jmp, block_idx);
Compile(node->_expr1);
AddCode(OP_PUSH_LOCAL, cond_res_idx);
// Jump to the end of the whole if-elif-else statement
// if the condition result was true
int exit_jmp = AddCode(OP_JMP_T, 0);
// Save index of the first code after this statement
int right_idx = function->_code.size();
function->ChangeCode(false_jmp, right_idx);
if (node->_expr2 != nullptr)
{
Compile(node->_expr2);
}
else
{
AddCode(OP_PUSH_NIL);
}
int end_idx = function->_code.size();
function->ChangeCode(exit_jmp, end_idx);
}
void CompileBinaryExpr(const BinaryExpr *expr)
{
auto function = _current_function;
auto token = expr->_op->type;
if (token == TOKEN_ASSIGN)
{
if (expr->_left->_type == NODE_SYMBOL)
{
int var = DeclareVar((Symbol *)expr->_left);
Compile(expr->_right);
AddCode(OP_STOR_LOCAL, var);
return;
}
}
// A function call
if (token == TOKEN_LEFTPAREN)
{
ArgList *arglist = (ArgList *)expr->_right;
auto args = arglist->_vec;
int argcount = args.size();
// A function call cannot have more than 255 arguments
assert(argcount < 256);
for (auto it = args.begin(), end = args.end();
it != end; it++)
{
Compile(*it);
}
Compile(expr->_left);
AddCode(OP_CALL, argcount);
return;
}
Compile(expr->_left);
// Both 'and' and 'or' expressions does short circuit
if (token == TOKEN_BOOL_AND ||
token == TOKEN_BOOL_OR)
{
AddCode(OP_DUP);
OpType op = (token == TOKEN_BOOL_AND) ? OP_JMP_F : OP_JMP_T;
int idx = AddCode(op, function->_ip + 1);
Compile(expr->_right);
int next = function->_code.size();
uint32_t instr = function->_code[idx];
function->ChangeCode(idx, next);
return;
}
// No need for lazy evaluation, compile normally
Compile(expr->_right);
switch (expr->_op->type)
{
case TOKEN_ADD:
AddCode(OP_ADD);
break;
case TOKEN_SUB:
AddCode(OP_SUB);
break;
case TOKEN_MUL:
AddCode(OP_MUL);
break;
case TOKEN_DIV:
AddCode(OP_DIV);
break;
case TOKEN_POW:
AddCode(OP_POW);
break;
case TOKEN_AND:
AddCode(OP_AND);
break;
case TOKEN_OR:
AddCode(OP_OR);
break;
case TOKEN_XOR:
AddCode(OP_XOR);
break;
case TOKEN_LT:
AddCode(OP_LT);
break;
case TOKEN_GT:
AddCode(OP_GT);
break;
case TOKEN_LTEQ:
AddCode(OP_LTEQ);
break;
case TOKEN_GTEQ:
AddCode(OP_GTEQ);
break;
case TOKEN_SHIFT_L:
AddCode(OP_SHIFT_L);
break;
case TOKEN_SHIFT_R:
AddCode(OP_SHIFT_R);
break;
}
}
void CompileUnaryExpr(const UnaryExpr *expr)
{
Compile(expr->_right);
switch (expr->_token->type)
{
case TOKEN_SUB:
AddCode(OP_NEGATE);
break;
case TOKEN_NOT:
AddCode(OP_NOT);
break;
case TOKEN_BOOL_NOT:
AddCode(OP_BOOL_NOT);
break;
}
}
// This function gets called only when it's a reference
void CompileSymbol(const Symbol *node)
{
auto token = node->_token;
char name[token->len + 1];
memcpy(name, token->pos, token->len);
name[token->len] = '\0';
DD1("Searching reference: ", name);
Value *upvalue = _ls->SearchVar(name);
if (upvalue)
{
int idx = _current_function->AddUpValue(upvalue);
AddCode(OP_PUSH_UPVALUE, idx);
return;
}
int idx = _current_function->GetLocalVarIndex(name);
AddCode(OP_PUSH_LOCAL, idx);
}
void CompileStringLiteral(const StringLiteral *sl)
{
Value v(sl->_token->str, sl->_token->len);
AddCode(OP_PUSH, AddConstant(v));
}
void CompileBoolLiteral(const BoolLiteral *bl)
{
Value v(bl->_token->type == TOKEN_TRUE);
AddCode(OP_PUSH, AddConstant(v));
}
void CompileIntLiteral(const IntLiteral *il)
{
Value v(il->_token->num);
AddCode(OP_PUSH, AddConstant(v));
}
int AddCode(OpType code)
{
return _current_function->AddCode(code);
}
int AddCode(OpType code, int a)
{
return _current_function->AddCode(code, a);
}
int AddConstant(const Value &v)
{
return _current_function->AddConstant(v);
}
};
The program outputs:
Declaring variable
0
It crashes before the DD("Variable declared") part.
Even though i'm new to C++, I'm pretty sure I don't need to allocate the unordered map myself, right? As it's not a pointer, it will be allocated when I do new LexState
So is there any initialization/allocation I am forgetting?
%i is not the right format specifier to use to print a pointer. You are most likely getting the output that represents a truncated value of the pointer. Use %p instead.
printf("%p\n", &state->_vars);
I don't see anything wrong using state->_vars. See working code at http://ideone.com/YAJK5K.
about data structures,why i can't output paths of the maze? I use the stack to storage the information of the current position.Read map of maze through a text file,if the position cant't pass
will be marker by "#",it is a wall.the way marker by "+". written in C++.
PS:My English is very poor.
//stack.h
#ifndef _STACK_H_
#define _STACK_H_
#include<iostream>
#include<stdlib.h>
const int SIZE = 81;
using namespace std;
typedef struct
{
int x;
int y;
}PosType;
typedef struct SElemType{
int ord;//steps
PosType seat;//coordinate
int di;//direction
}SElemType;
typedef struct SqStack{
SElemType *base;
SElemType *top;
int StackSize;
}SqStack;
void Init_S(SqStack &S)
{
S.base = new SElemType[SIZE];
if(!S.base)
exit(EXIT_FAILURE);
S.top = S.base;
S.StackSize = SIZE;
}
bool StackEmpty(SqStack S)
{
if(S.top = S.base)
return true;
return false;
}
void Push(SqStack &S,SElemType e)
{
SElemType *newbase;
if(S.top-S.base>=S.StackSize)
{
newbase = new SElemType[S.StackSize*2];
if(!S.base)
exit(EXIT_FAILURE);
for(int i(0);i<S.top-S.base;i++)
*(newbase+i) = *(S.base+i);
delete[]S.base;
S.base = newbase;
S.top = S.base+S.StackSize;
S.StackSize *= 2;
}
*(S.top)++ = e;
}
void Pop(SqStack &S,SElemType e)
{
if(StackEmpty(S))
cout<<"empty stack!\n";
else
e = *(--S.top);
}
#endif
//maze.cpp
#include<iostream>
#include<cstdlib>
#include<fstream>
#include"stack.h"
using namespace std;
const int m = 10;
const int n = 10;
typedef char MazeG[m][n];
void Show_MG(MazeG MG)
{
for(int i(0);i<m;i++)
{
for(int j(0);j<n;j++)
{
cout<<MG[i][j];
}
cout<<"\t\n";
}
}
PosType Next(PosType &pos,int di)
{
PosType repos;
switch(di)
{
case 0://north
repos.x = pos.x-1;
repos.y = pos.y;
break;
case 1://east
repos.x = pos.x;
repos.y = pos.y+1;
break;
case 2://south
repos.x = pos.x+1;
repos.y = pos.y;
break;
case 3://west
repos.x = pos.x;
repos.y = pos.y-1;
break;
default:
break;
}
return repos;
}
int MazePath(MazeG &MG,PosType begin,PosType end)
{
PosType curpos = begin;
SqStack S;
Init_S(S);
SElemType e;
e.ord = 0;
do{
if(MG[curpos.x][curpos.y]=='*')
{
MG[curpos.x][curpos.y] = '+';
e.seat = curpos;
e.di = 0;
e.ord++;
Push(S,e);
if(curpos.x==end.x&&curpos.y==end.y)
{
cout<<"此迷宫的一条路径如下:(+标记为路径)\n";//the path of maze:
cout<<"走了"<<e.di<<"步到达出口\n";//The number of steps walked
Show_MG(MG);
return 0;
}
else
curpos = Next(curpos,e.di);
}
else
if(!StackEmpty(S))
{
Pop(S,e);
e.ord--;
while(e.di==3&&!StackEmpty(S))
{
MG[curpos.x][curpos.y] = '#';
Pop(S,e);
e.ord--;
}
if(e.di<3)
{
e.di++;
Push(S,e);
e.ord++;
curpos = Next(curpos,e.di);
}
}
}while(!StackEmpty(S));
cout<<"此迷宫没有入口到出口的路径!\n";//no path of the maze
//return -1;
}
int main()
{
MazeG MG;
PosType begin,end;
begin.x = 1; begin.y = 1;
end.x = 8; end.y = 8;
ifstream fin;
fin.open("file.txt");
if(!fin.is_open())
{
cout<<"erorr file!!\n";
exit(EXIT_FAILURE);
}
if(fin.good())
{
for(int i(0);i<m;i++)
for(int j(0);j<n;j++)
fin>>MG[i][j];
}
cout<<"迷宫图为:(*代表能通过)\n";//map of maze:('*' is means through)
Show_MG(MG);
cout<<begin.x<<begin.y<<end.x<<end.y<<endl;
fin.close();
MazePath(MG,begin,end);
return 0;
}
This is wrong
bool StackEmpty(SqStack S)
{
if(S.top = S.base)
return true;
return false;
}
It should be this
bool StackEmpty(SqStack S)
{
if(S.top == S.base) // == not =
return true;
return false;
}
Use == for equality not =.
Now,I understand my the error of code is that I mismatch the data will be stored by stack.
I have changed my code,that's right.
//stack.h
SElemType Gettop(SqStack S)
{
if(!Empty_S(S))
return *(S.top-1);
}
//maze_path.cpp
do{
if(MG[curpos.x][curpos.y]=='*')
{
MG[curpos.x][curpos.y] = '+';
e.seat = curpos;
e.di = 0;
e.ord++;
Push(S,e);
if(curpos.x==end.x&&curpos.y==end.y)
{
cout<<"此迷宫的一条路径如下:(+标记为路径)\n";//the path of maze:
cout<<"走了"<<e.di<<"步到达出口\n";//The number of steps walked
Show_MG(MG);
return 0;
}
else
curpos = Next(curpos,e.di);
}
else
if(!StackEmpty(S))
{
if(e.di<3)
{
e.ord++;
curpos = Next(curpos,e.di);
}
else
{
MG[curpos.x][curpos.y] = '#';
Pop(S,e);
e = Gettop(S);
}
}
}while(!StackEmpty(S));
I have below class
class Cdata12Mnt
{
public:
char IOBname[ID1_IOB_PIOTSUP-ID1_IOB_TOP][BOADNAM_MAX + 4];
char ExIOBname[ID1_MAX_INF-ID1_EXIOB_U1TOP][BOADNAM_MAX + 4];
char cflpath[256];
char basetext[256];
UINT database[ID1_MAX_INF];
int State;
public:
char SelectPath[256];
public:
int GetIOBName(int slt,char *Name);
Cdata12Mnt(char *SelectPath);
virtual ~Cdata12Mnt();
int GetValue(int id);
int GetState() { return State; }
};
And I have function as below
Cdata12Mnt::Cdata12Mnt(char *SelectPath)
{
SCTReg reg;
char buf[256], *cpnt, *npnt, *bpnt1, *bpnt2;
char *startcode[] = {"CNTL_CODE ","SEGMENT "};
char *stopcode = {"END_CNTL_CODE "};
FILE *fp;
int ii, infl;
State = 0;
for (ii = 0; ii < (ID1_IOB_PIOTSUP - ID1_IOB_TOP); ii++) {
strcpy(IOBname[ii], "");
}
for (ii = 0; ii < (ID1_MAX_INF-ID1_EXIOB_U1TOP); ii++) {
**strcpy(ExIOBname[ii], "");**
}
sprintf(cflpath, "%s\\%s", SelectPath, CDATAFL);
if ((fp = fopen(cflpath,"r"))!=NULL) {
for (ii = 0, infl = 0; fgets(buf, 256, fp) != NULL;) {
if (infl == 0 && strncmp(buf, startcode[0], strlen(startcode[0])) == 0) {
if ((cpnt = strchr(&buf[strlen(startcode[0])],*startcode[1])) != NULL) {
if (strncmp(cpnt,startcode[1], strlen(startcode[1])) == 0) {
infl = 1;
continue;
}
}
}
if (infl == 0) {
continue;
}
if (strncmp(buf,stopcode,strlen(stopcode))==0) {
if (ii == ID1_EXIOB_U1TOP) {
for (int nDataNumber = ii; nDataNumber < ID1_MAX_INF; nDataNumber++) {
database[nDataNumber] = 0;
}
}
infl = 0;
continue;
}
if (strncmp(&buf[14], " DD ", 4) == 0) {
if ((cpnt=strchr(buf, ';')) != NULL) {
*cpnt = '\0';
}
if (ii >= ID1_IOB_TOP && ii < ID1_IOB_PIOTSUP) {
if ((bpnt1 = strchr(cpnt + 1,'(')) != NULL && (bpnt2=strchr(cpnt + 1,')'))!=NULL && bpnt1 < bpnt2) {
*bpnt2 = '\0';
*(bpnt1 + BOADNAM_MAX + 1) = '\0';
strcpy(IOBname[ii-ID1_IOB_TOP], bpnt1 + 1);
}
}
if (ii >= ID1_EXIOB_U1TOP && ii < ID1_MAX_INF) {
if ((bpnt1 = strchr(cpnt + 1, '(')) != NULL && (bpnt2=strchr(cpnt+1,')'))!=NULL && bpnt1 < bpnt2) {
*bpnt2='\0';
*(bpnt1+BOADNAM_MAX+1)='\0';
strcpy(ExIOBname[ii-ID1_EXIOB_U1TOP], bpnt1 + 1);
}
}
for (cpnt = &buf[18]; cpnt != NULL;) {
if ((npnt=strchr(cpnt, ',')) != NULL)
*npnt='\0';
}
if (strchr(cpnt,'H')!=NULL) {
sscanf(cpnt,"%XH",&database[ii]);
} else {
database[ii]=atoi(cpnt);
}
ii++;
cpnt = npnt;
if (cpnt != NULL) {
cpnt++;
}
}
}
}
fclose(fp);
} else {
State=-1;
}
When I compile this function in Visual studio 2008, it gives me error at strcpy(IOBname[ii],""); as below
error C2220: warning treated as error - no 'object' file generated
How to fix this error?
The error says that a warning was treated as an error, therefore your problem is a warning message! The object file is then not created because there was an error. So you need to check your warnings and fix them.
In case you don't know how to find them: Open the Error List (View > Error List) and click on Warning.
Go to project properties -> configurations properties -> C/C++ -> treats warning as error -> No (/WX-).
As a side-note, you can enable/disable individual warnings using #pragma. You can have a look at the documentation here
From the documentation:
// pragma_warning.cpp
// compile with: /W1
#pragma warning(disable:4700)
void Test() {
int x;
int y = x; // no C4700 here
#pragma warning(default:4700) // C4700 enabled after Test ends
}
int main() {
int x;
int y = x; // C4700
}
This error message is very confusing. I just fixed the other 'warnings' in my project and I really had only one (simple one):
warning C4101: 'i': unreferenced local variable
After I commented this unused i, and compiled it, the other error went away.
This warning is about unsafe use of strcpy. Try IOBname[ii]='\0'; instead.
I have a struct defined as follows
struct VariableList
{
void Add(simple_instr* instr)
{
//PrintOpcode(instr);
switch(instr->opcode)
{
case STR_OP:
case MCPY_OP:
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
case LDC_OP:
Add(instr->u.ldc.dst);
break;
case BTRUE_OP:
case BFALSE_OP:
Add(instr->u.bj.src);
break;
case CALL_OP:
if (instr->u.call.dst != NO_REGISTER)
{
Add(instr->u.call.dst);
}
Add(instr->u.call.proc);
for (int i = 0; i < instr->u.call.nargs; i++)
{
Add(instr->u.call.args[i]);
}
break;
case MBR_OP:
Add(instr->u.mbr.src);
break;
case RET_OP:
if (instr->u.base.src1 != NO_REGISTER)
Add(instr->u.base.src1);
break;
case CVT_OP:
case CPY_OP:
case NEG_OP:
case NOT_OP:
case LOAD_OP:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
break;
case LABEL_OP:
case JMP_OP:
break;
default:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
}
}
void Add(Variable var)
{
variableList.push_back(var);
}
void RemoveDuplicates()
{
if (variableList.size() > 0)
{
variableList.erase(unique(variableList.begin(), variableList.end()), variableList.end());
currentID = variableList.size();
}
}
VariableList()
{
currentID = 0;
dynamicallyCreated = false;
}
VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
{
currentID = 0;
for (int i = 0; i < varList.size(); i++)
{
Variable* var = new Variable(varList[i]);
if (setLiveness)
{
var->isLive = LiveVal;
}
variableList.push_back(*var);
}
dynamicallyCreated = variableList.size() > 0;
}
Variable& operator[] (int i)
{
return variableList[i];
}
int size()
{
return variableList.size();
}
vector<Variable>::iterator begin()
{
return variableList.begin();
}
vector<Variable>::iterator end()
{
return variableList.end();
}
bool CompareLiveness(VariableList &var)
{
if(variableList.size() != var.size())
{
return false;
}
for (int i = 0; i < variableList.size(); i++)
{
if(variableList[i].isLive != var[i].isLive)
return false;
}
return true;
}
~VariableList()
{
if(dynamicallyCreated)
{
for (vector<Variable>::iterator it = variableList.begin(); it < variableList.end(); ++it)
{
//delete (&it);
}
}
}
protected:
int currentID;
vector<Variable> variableList;
bool dynamicallyCreated;
void Add(simple_reg* reg, bool checkForDuplicates = false)
{
if (reg == null)
{
cout << "null detected" << endl;
return;
}
if (reg->kind == PSEUDO_REG)
{
if (!checkForDuplicates || (checkForDuplicates && find(variableList.begin(), variableList.end(), reg->num) != variableList.end()))
{
cout << "Adding... Reg " << reg->num << endl;
Variable* var = new Variable(reg->num, currentID);
variableList.push_back(*var);
currentID++;
}
}
}
};
I'd like to be able to do a statement like this
VariableList varsIn(Variables, true, false);
that will create a deep copy and allow me to change a few properties. As you can see in my struct, I'm currently attempting to do this using
VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
{
currentID = 0;
for (int i = 0; i < varList.size(); i++)
{
Variable* var = new Variable(varList[i]);
if (setLiveness)
{
var->isLive = LiveVal;
}
variableList.push_back(*var);
}
dynamicallyCreated = variableList.size() > 0;
}
I don't think this is the right way to do it though. What's the proper way to do this sort of copying? Is there a way to do it without using new? For reference, the Variable struct is as follows
struct Variable
{
int id;
int num;
bool isLive;
simple_op opcode;
Variable()
{
id = 0;
num = 0;
opcode = NOP_OP;
vClass = Basic;
isLive = false;
}
Variable(int _num, int _id = 0, simple_op _op = NOP_OP)
{
id = _id;
num = _num;
opcode = _op;
vClass = Basic;
isLive = false;
}
VariableClass GetClass()
{
return vClass;
}
bool operator==(const Variable &var) const
{
return num == var.num;
}
bool operator==(const int &x) const
{
return x == num;
}
protected:
VariableClass vClass;
};
VariableClass and simple_op are enums
Thanks in advance
Your code is not only doing dynamic allocation unnecessarily, it's also leaking Variable instances everywhere. Just use an automatic variable, push_back will make a copy:
VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
{
currentID = 0;
for (int i = 0; i < varList.size(); i++)
{
Variable var(varList[i]);
if (setLiveness)
{
var.isLive = LiveVal;
}
variableList.push_back(var);
}
}
And take out the destructor, you can't delete the elements owned by the vector. If they pointed somewhere, sure, but you're not storing pointers.
Also, here's an even better way:
VariableList(VariableList& other, bool setLiveness = false, bool LiveVal = false)
: currentID(0)
, variableList(other.variableList)
{
if (setLiveness) {
for( int i = 0; i < size(); i++ )
variableList[i].isLive = LiveVal;
}
}