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 5 years ago.
Improve this question
So im creating an engine from scrath(learnign purposes).
And when i test my TArray i get an Execption thrown in my Memory.h file. This happens only when im trying to test the TArray
Here is my code for TArray.h
#pragma once
#include "Memory/DynamicLinearStackAllocator.h"
template <typename T, typename Allocator = DynamicLinearStackAllocator>
class TArray
{
private:
Allocator m_Allocator;
uint32 m_ElementCount;
public:
FORCEINLINE TArray()
{
}
FORCEINLINE ~TArray()
{
m_Allocator.Destroy();
}
FORCEINLINE TArray(const uint32 InElementCount)
{
m_Allocator.Resize<T>(InElementCount, m_ElementCount);
m_ElementCount = InElementCount;
}
FORCEINLINE void Add(const T &InValue)
{
}
FORCEINLINE T* GetData() const { return m_Allocator.GetAllocator<T>(); }
FORCEINLINE uint32 Num() const
{
return m_ElementCount;
}
FORCEINLINE T& operator[](uint32 InElementIndex) const
{
check(m_ElementCount > InElementIndex);
return GetData()[InElementIndex];
}
};
namespace Tests
{
FORCEINLINE void TestArrays()
{
{
TArray<float> data(10);
check(data.Num() == 10);
for(uint32 i = 0; i < data.Num(); i++)
{
data[i] = 2.0f;
}
check(data[0] == 2.0f);
}
{
TArray<uint32> data(5);
data[0] = 10;
data[1] = 5;
check(data.Num() == 5);
check(data[0] == 10);
check(data[1] == 5);
}
{
TArray<float> data(1);
data[2] = 2.0f;
}
}
}
When i try to compile(Im using Visual Studio 2017) it gives me an execption error at this position in Memory.h
static void* Copy(void *InDestination, const void *InSource, size_t InSize)
{
check_slow(InDestination);
check_slow(InSource);
check_slow(InSize > 0);
return memcpy(InDestination, InSource, InSize);
}
The test is getting called in the main function with this code:
int main()
{
Tests::TestAssertion();
Tests::TestMemory();
Tests::TestAllocator();
Tests::TestArrays();
return 0;
}
my goal currently is to look if the logger shows me the error here:
{
TArray<float> data(1);
data[2] = 2.0f;
}
here is a screenshot of the full error https://gyazo.com/6c1d6779623ffea97504f5b23f9fd7da
edit: here is the code for the allocator
#pragma once
#include <malloc.h>
#include "Core.h"
#define MEMORY_ALIGMENT 16
struct Memory
{
// TODO:Rework types.
static void* Allocate(const int32 InCount, const size_t InSize)
{
check_slow(InCount > 0);
check_slow(InSize > 0);
const size_t size = InSize * InCount;
return _aligned_malloc(size, MEMORY_ALIGMENT);
}
static void Free(void *InBlock)
{
check_slow(InBlock);
_aligned_free(InBlock);
}
static void* Copy(void *InDestination, const void *InSource, size_t InSize)
{
check_slow(InDestination);
check_slow(InSource);
check_slow(InSize > 0);
return memcpy(InDestination, InSource, InSize);
}
};
void* operator new (size_t InSize)
{
return Memory::Allocate(1, InSize);
}
void operator delete (void* InBlock)
{
Memory::Free(InBlock);
}
namespace Tests
{
struct MemoryTestStruct
{
uint32 p0;
uint32 p1;
uint32 p2;
uint32 p3;
};
FORCEINLINE void TestMemory()
{
MemoryTestStruct *t = new MemoryTestStruct();
check(t);
delete t;
}
}
edit2: Here is the code for the StackAlloctor
#pragma once
#include "../Core.h"
class DynamicLinearStackAllocator
{
private:
void *m_Data;
public:
template <typename T>
FORCEINLINE void Resize(const uint32 InElementCount, const uint32 InPreviousElementCount)
{
void *temp = Memory::Allocate(InElementCount, sizeof(T));
if (InPreviousElementCount > 0)
{
const SIZE_T size = sizeof(T) * InPreviousElementCount;
Memory::Copy(temp, m_Data, size);
Memory::Free(m_Data);
}
m_Data = temp;
}
template <typename T>
FORCEINLINE T* GetAllocator() const
{
return (T*)m_Data;
}
FORCEINLINE void Destroy()
{
Memory::Free(m_Data);
}
};
namespace Tests
{
FORCEINLINE void TestAllocator()
{
DynamicLinearStackAllocator alloc;
alloc.Resize<float>(2, 0);
alloc.Destroy();
}
}
You're not showing the code for your Allocator, but the problem is probably this line in your TArray constructor:
m_Allocator.Resize<T>(InElementCount, m_ElementCount);
At this point, m_ElementCount has not been initialized and will have some random value in it. Resize is then probably trying to free up memory that hasn't been allocated (because of the uninitialized value in m_ElementCount). You should pass in a 0 for the second parameter of the Resize call in your constructor
m_Allocator.Resize<T>(InElementCount, 0);
since there is no existing allocated memory to free.
Also, your default constructor for TArray should initialize m_Allocator.m_data to nullptr (or add a default constructor to DynamicLinearStackAllocator to do that) and set m_ElementCount to 0.
Related
I want to build a Memory Management to avoid memory leak but my code has an error that I have no idea how to fix, and how to fix the error in the code?
There: EMC_DELETE cls2; // <-- error: expected a ';'
This code is referenced from a GLSL parser (https://github.com/graphitemaster/glsl-parser/blob/main/ast.h).
// A helper function to help other to reproduce the same example.
std::string pathFolderOrFileName(const std::string &path) {
return path.substr(path.find_last_of("/\\") + 1);
}
template <typename T>
static inline void _destroy(void *self) {
((T*)self)->~T();
free(self);
}
struct Memory {
// Memory Management that's referenced from "emc-language > lexer-parser > ast.h".
Memory() : data(0), dtor(0) { }
template <typename T>
Memory(T *data, const char *file, int line) :
data((void*)data),
dtor(&_destroy<T>),
file(file),
line(line)
{}
void *data;
void (*dtor)(void*);
const char *file;
int line;
void destroy() {
dtor(data);
}
};
template <typename T>
struct Node {
void *operator new(size_t size, std::vector<Memory> *collector, const char *file, int line) throw() {
void *data = malloc(size);
if (data) {
collector->push_back(Memory((T *)data, file, line));
}
return data;
}
void operator delete(void *data, std::vector<Memory> *collector) {
auto &vec = *collector;
for (int i = 0; i < vec.size(); i++) {
if (vec[i].data == data) {
vec.erase(vec.begin() + i);
free(data);
return;
}
}
assert(0);
}
};
// Note: Never use the default 'operator new & delete' because they can cause memory leak.
#define EMC_NEW new(&g_memory, __FILE__, __LINE__) // Use this instead of using the default 'operator new'.
#define EMC_DELETE delete(&g_memory) // Use this instead of using default 'operator delete'.
//----------------------------------------------------------------------------------------------------
class MyBaseClass {
public:
int base_x, base_y;
};
class MyClass : public Node<MyClass> {
public:
int x, y;
MyClass() {
}
~MyClass() {
}
};
std::vector<Memory> g_memory;
int main() {
MyClass *cls0 = EMC_NEW MyClass();
MyClass *cls1 = EMC_NEW MyClass();
MyClass *cls2 = EMC_NEW MyClass();
EMC_DELETE cls2; // <-- error: expected a ';'
for (int i = 0; i < g_memory.size(); i++) {
auto &it = g_memory[i];
printf("%d: (file \"%s\", line %d)\n", i, pathFolderOrFileName(it.file).c_str(), it.line);
}
return 0;
}
Expected output:
0: (file "test_draft.cpp", line 79)
1: (file "test_draft.cpp", line 80)
2: (file "test_draft.cpp", line 81) this line must be removed because cls2 must be deleted.
I have implemented a serializer to send data over network. And I have implemented a system that can deserialize primitive data, string, map(string, string), map(string, float), but the error happens with map(string, int) when the deserialized map is used to fetch the value from key. In the debugger I can see that map receive correct value but when I'm trying to get data, I get an error "std::out_of_range at memory location".
Here is my code
#include <stdint.h>
#include <memory>
#include <string>
#include <map>
#include <algorithm>
#define STREAM_ENDIANNESS 0
#define PLATFORM_ENDIANNESS 0
using namespace std;
class OutputMemoryStream
{
void ReallocBuffer(uint32_t inNewLength)
{
mBuffer = static_cast<char*>(std::realloc(mBuffer, inNewLength));
mCapacity = inNewLength;
}
char* mBuffer = nullptr;
uint32_t mHead;
uint32_t mCapacity;
public:
OutputMemoryStream() : mHead(0) { ReallocBuffer(32); }
~OutputMemoryStream()
{
if (mBuffer) { mBuffer = nullptr; }
}
char* GetBufferPtr() const { return mBuffer; }
uint32_t GetLength() const { return mHead; }
void Write(const void* inData, size_t inByteCount)
{
//make sure we have space...
uint32_t resultHead = mHead + static_cast<uint32_t>(inByteCount);
if (resultHead > mCapacity)
{
ReallocBuffer(std::max(mCapacity * 2, resultHead));
}
//copy into buffer at head
std::memcpy(mBuffer + mHead, inData, inByteCount);
//increment head for next write
mHead = resultHead;
}
template< typename T > void Write(T inData)
{
static_assert(std::is_arithmetic< T >::value || std::is_enum< T >::value, "Generic Write only supports primitive data types");
if (STREAM_ENDIANNESS == PLATFORM_ENDIANNESS)
{
Write(&inData, sizeof(inData));
}
else { }
}
template< typename T >
void Write(const std::map< string, T >& inMap)
{
uint32_t elementCount = inMap.size();
Write(elementCount);
for (std::pair<string, T> element : inMap)
{
Write(element.first);
Write(element.second);
}
}
void Write(const std::string& inString)
{
size_t elementCount = inString.size();
Write(elementCount + 1);
Write(inString.data(), (elementCount + 1) * sizeof(char));
}
};
class InputMemoryStream
{
private:
char* mBuffer;
uint32_t mHead;
uint32_t mCapacity;
public:
InputMemoryStream() {}
InputMemoryStream(char* inBuffer, uint32_t inByteCount) : mBuffer(inBuffer), mCapacity(inByteCount), mHead(0) { }
~InputMemoryStream()
{
if (mBuffer) { mBuffer = nullptr; }
}
uint32_t GetRemainingDataSize() const
{
return mCapacity - mHead;
}
void Read(void* outData, uint32_t inByteCount)
{
uint32_t resultHead = mHead + inByteCount;
if (resultHead > mCapacity)
{
//handle error, no data to read!
//...
}
std::memcpy(outData, mBuffer + mHead, inByteCount);
mHead = resultHead;
}
template< typename T > void Read(T& outData)
{
static_assert(std::is_arithmetic< T >::value || std::is_enum< T >::value, "Generic Read only supports primitive data types");
Read(&outData, sizeof(outData));
}
template<typename T1>
void Read(std::map<string, T1> &mapP)
{
size_t elemenCount;
Read(elemenCount);
for (int i = 0; i < elemenCount; i++)
{
string key; T1 value;
Read(key);
Read(value);
std::pair<string, T1> pair(key, value);
mapP.insert(pair);
}
}
void Read(string &outString)
{
size_t strSize;
Read(strSize);
outString.resize(strSize);
for (int i = 0; i < strSize; i++)
{
Read(&outString[i], 1);
}
}
};
class ServerObject
{
OutputMemoryStream outStream;
InputMemoryStream inStream;
map<std::string, int> mapInt;
public:
ServerObject() {};
ServerObject(char* byteArray, int byteCount)
{
InputMemoryStream inStream(byteArray, byteCount);
Deserialize(inStream);
}
~ServerObject() {};
void Serialize()
{
outStream.Write(mapInt);
}
void Deserialize(InputMemoryStream inStream)
{
inStream.Read(mapInt);
}
OutputMemoryStream GetOutStream()
{
return outStream;
}
int GetInt(string key)
{
return mapInt.at(key);
}
void PutInt(string key, int value)
{
mapInt.insert(std::pair<string, int>(key, value));
}
};
int main()
{
ServerObject * so = new ServerObject();
so->PutInt("test", 10);
so->Serialize();
ServerObject * so1 = new ServerObject(so->GetOutStream().GetBufferPtr(), so->GetOutStream().GetLength());
int i = so1->GetInt("test");
system("pause>NULL");
return 0;
}
Your void Write(const std::string& inString) function of OutputMemoryStream should not store additional byte of buffer for null terminator because std::string will not contain null terminator but if you use c_str(), a null terminator will be included in the return from this method. Don't get confused with the internal structure of the memory. std::string stores the length of the string in its member variable so there is no need of null terminator. The function should be as shown below.
void Write(const std::string& inString)
{
size_t elementCount = inString.size();
Write(elementCount);
Write(inString.data(), elementCount * sizeof(char));
}
I have a problem declaring a public/extern struct object between different .cpp files. I am trying to use the imgui logger to log some messages from a hook.
The program is going to crash on ExampleAppLog my_log2; -> ImGuiTextBuffer Buf; -> class ImVector -> if (Data)
Because i do this ExampleAppLog* my_log2 = new ExampleAppLog(); inside a .cpp that have a include .h with the struct ExampleAppLog in it, and a declaration of my_log2 .
Relevant code to crash ->
.h
struct ExampleAppLog
{
ImGuiTextBuffer Buf;
}
extern ExampleAppLog* my_log2;
.cpp
#include ".h"
ExampleAppLog* my_log2 = new ExampleAppLog(); //this line make it crash
imgui.h
struct ImGuiTextBuffer
{
ImVector<char> Buf;
}
class ImVector
{
public:
int Size;
int Capacity;
T* Data;
typedef T value_type;
typedef value_type* iterator;
typedef const value_type* const_iterator;
ImVector() { Size = Capacity = 0; Data = NULL; }
~ImVector() { if (Data) ImGui::MemFree(Data); }
inline bool empty() const { return Size == 0; }
inline int size() const { return Size; }
inline int capacity() const { return Capacity; }
inline value_type& operator[](int i) { IM_ASSERT(i < Size); return Data[i]; }
inline const value_type& operator[](int i) const { IM_ASSERT(i < Size); return Data[i]; }
inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } }
inline iterator begin() { return Data; }
inline const_iterator begin() const { return Data; }
inline iterator end() { return Data + Size; }
inline const_iterator end() const { return Data + Size; }
inline value_type& front() { IM_ASSERT(Size > 0); return Data[0]; }
inline const value_type& front() const { IM_ASSERT(Size > 0); return Data[0]; }
inline value_type& back() { IM_ASSERT(Size > 0); return Data[Size-1]; }
inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size-1]; }
inline void swap(ImVector<T>& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }
inline int _grow_capacity(int size) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > size ? new_capacity : size; }
inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; }
inline void resize(int new_size, const T& v){ if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) Data[n] = v; Size = new_size; }
inline void reserve(int new_capacity)
{
if (new_capacity <= Capacity) return;
T* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(T));
if (Data) //here is the crash. Data is 0x000000000 when crashing
memcpy(new_data, Data, (size_t)Size * sizeof(T));
ImGui::MemFree(Data);
};
Exsample code ->
.h
struct ExampleAppLog
{
ImGuiTextBuffer Buf;
ImGuiTextFilter Filter;
ImVector<int> LineOffsets; // Index to lines offset
bool ScrollToBottom;
void Clear() { Buf.clear(); LineOffsets.clear(); }
void AddLog(const char* fmt, ...) IM_FMTARGS(2)
{
int old_size = Buf.size();
va_list args;
va_start(args, fmt);
Buf.appendv(fmt, args);
va_end(args);
for (int new_size = Buf.size(); old_size < new_size; old_size++)
if (Buf[old_size] == '\n')
LineOffsets.push_back(old_size);
ScrollToBottom = true;
}
void Draw(const char* title, bool* p_open = NULL)
{
ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
ImGui::Begin(title, p_open);
if (ImGui::Button("Clear")) Clear();
ImGui::SameLine();
bool copy = ImGui::Button("Copy");
ImGui::SameLine();
Filter.Draw("Filter", -100.0f);
ImGui::Separator();
ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
if (copy) ImGui::LogToClipboard();
if (Filter.IsActive())
{
const char* buf_begin = Buf.begin();
const char* line = buf_begin;
for (int line_no = 0; line != NULL; line_no++)
{
const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
if (Filter.PassFilter(line, line_end))
ImGui::TextUnformatted(line, line_end);
line = line_end && line_end[1] ? line_end + 1 : NULL;
}
}
else
{
ImGui::TextUnformatted(Buf.begin());
}
if (ScrollToBottom)
ImGui::SetScrollHere(1.0f);
ScrollToBottom = false;
ImGui::EndChild();
ImGui::End();
}
};
extern ExampleAppLog* my_log2;
One.cpp
#include ".h"
ExampleAppLog* my_log2 = new ExampleAppLog(); //this line make it crash
void LogHook(const char* Info)
{
my_log2->AddLog(Info);
}
Two.cpp
#include ".h"
bool bDraw = true;
void Draw()
{
my_log2->Draw("Logger", &bDraw);
}
I have tried many different methodes but no luck without it ending up crashing when trying to share a extern object in multiple .cpp.
Logger documentation.
static ExampleAppLog my_log; //have tryd this but with extern etc. It still crash at the same place whan trying to share it globaly. If i do it all in one .cpp out sharing it publicly the code work
[...]
my_log.AddLog("Hello %d world\n", 123);
[...]
my_log.Draw("title");
It is hard to tell you what your problem is because important information is missing.
Are you sure that it crash while checking if Data is a null pointer?
Have you checked if this is valid at the point of crash?
Have you put a breakpoint on the constructor to see when it was called.
While it looks like you don't make any copy of those objects, it would be a good idea to prevent it if not properly supported by deleting copy and move constructor and assignment operators. See https://en.cppreference.com/w/cpp/language/function#Deleted_functions for more information.
One obvious way to see if the problem is that you call a function of ExampleAppLog before it is created is to put a breakpoint inside the constructor. From the above code, we cannot be sure if the class is created only once or multiple times (from elsewhere).
Also are you sure that you don't call Draw or LookHook before you create my_log2 object. Again, that kind of thing is trivial to test with a debugger but very hard for us to tell with only part of the code in our hand. In fact, as the above program does not have a main, it is not a MCVE.
If it really crashes when you are creating ExampleAppLog object and not when trying to use it before it was created, then most of the code above is useless and commenting out code (and remove it from the question) if it still crash, would greatly help people to help you.
On the other hand, if it crash because you are using my_log2 before it is created, then some required code to reproduce the problem is missing.
If the problem is related to initialisation order, then a singleton might be the solution. Look at the accepted answer here: How to implement multithread safe singleton in C++11 without using <mutex>.
In any case, it is hard to help you because you don't put enough effort in your question. Remember that if the code cannot easily be copied and paste, almost nobody will take the time to create a project even more when it is obvious that important lines or information are missing because with the provided information, it is almost impossible that it crash on the specified line.
In fact, in we assume that main is an empty function and that there are no other global usage of either my_log2 pointer and ExampleAppLog struct, then when would the function reserve be called.
As a bonus, if you ask good questions, you get more points on the site!
This question already has answers here:
How to initialize const member variable in a class?
(11 answers)
Closed 7 years ago.
So I've looked around and nothing I found has helped me so far.
I have the following header file for my class.
#ifndef CONGERA2_H
#define CONGERA2_H
typedef float Element300;
class Stack300
{
public:
Stack300 ();
Stack300 (const int);
Stack300 (Stack300 &old);
~Stack300();
void push300(const Element300);
Element300 pop300();
void viewTB300();
void viewBT300();
private:
const int MAX_STACK;
Element300 * stackArray;
int top;
};
#endif
And I'm trying to initialize MAX_STACK. If I set it equal to something I get a warning, which would normally be fine but I must transfer this code to Linux afterwards and I can't do that because it says that MAX_STACK is undefined in my three constructors. I've also tried defining it in my class functions file in the first constructor but then I get an error saying that MAX_STACK is not defined in the constructor.
Here is the constructors for my class functions if they are needed.
#include <iostream>
#include "congera2.h"
using namespace std;
Stack300::Stack300 (): MAX_STACK(10)
{
stackArray = new float[3];
for (int i = 0; i < 3; i++)
{
stackArray[i] = '\0';
}
top = -1;
return;
}
Stack300::Stack300 (const int size) : MAX_STACK (10)
{
stackArray = new float[MAX_STACK];
for (int i = 0; i < MAX_STACK; i++)
{
stackArray[i] = '\0';
}
top = -1;
return;
}
Stack300::Stack300 (Stack300 &old) : MAX_STACK (10)
{
top = old.top;
int i = 0;
while (top != old.top)
{
stackArray[i] = old.stackArray[i];
i = i + 1;
top = i;
}
}
Error:
class A
{
public:
const int x=8; // error (c++98/03)
};
Fix 1
class A
{
public:
const int x;
A() : x(8) // ok
{ }
};
Fix 2
class A
{
public:
const static int x;
};
const int A::x=8; // ok
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 8 years ago.
Improve this question
I'm getting these results:
constructor
setFunc
setFunc
Basically I want my class-object globally and pass the struct array to setMethod of the class. and Program is successfully compiling but not getting any results.
DataInput.h
#ifndef DATAINPUT_H_
#define DATAINPUT_H_
#include <stdio.h>
struct Data{
const char *name;
int salary;
void set(int salary, const char *name){
printf("setFunc \n");
this->name = name;
this->salary = salary;
}
};
This class in a seprate cpp file with above header file
class DataInput {
public:
int dataSize;
struct Data data[];
DataInput();
virtual ~DataInput();
void setData(struct Data d[], int numberOfData);
void printData();
private:
};
#endif
-------eof----------
DataInput.cpp
#include "DataInput.h"
DataInput::DataInput() {
printf("constructor \n");
dataSize = 0;
}
DataInput::~DataInput() {
}
void DataInput :: setData(struct Data d[], int numberOfData){
dataSize = numberOfData;
for (int i = 0; i< numberOfData; i++){
printf("i-val in setData() --> %d",i);
this->data[i] = data[i];
}
}
void DataInput::printData(){
for (int i = 0; i< dataSize; i++){
printf("name--> %s \n",data[i].name);
printf("salary--> %d \n",data[i].salary);
}
}
--------eof-----------
main.cpp
#include <stdlib.h>
#include "DataInput.h"
#include <stdio.h>
DataInput *dataInput;
int main(void) {
DataInput in;
dataInput = ∈
struct Data d[2];
d[0].set(1000, "ABC");
d[1].set(2000, "XYZ");
dataInput->setData(d, 2); //not setting data
dataInput->printData(); //not printing
return 0;
}
Note: May not compile, is just illustrative
Few things:
DataInputconstructor do not reserve space for new items. So, this->data[i] = data[i]; result is undefined.
This is C++, Rule of three, strings, ....
struct Data
{
std::string name;
int salary;
Data(const std::string & n, int s);
Data & operator=(const Data & d);
};
Data::Data(const std::string & n, int s) :
name(n), salary(s)
{
}
Data & Data::operator=(const Data & d)
{
name = d.name;
salary = d.salary;
return *this;
}
Use standards containers:
class DataInput
{
private:
std::vector<Data> data;
public:
DataInput();
virtual ~DataInput();
// you don't need use size
void setData(const std::vector<Data> & d);
void printData();
};
void DataInput::setData(const std::vector<Data> & d)
{
data = d;
}
void DataInput::printData()
{
for (std::vector<Data>::iterator it = data.begin(); it != data.end(); ++it)
{
std::cout << it->name << ":" << it->salary << std::endl;
}
}
Now, you can use it from main (without pointers):
int main(void)
{
DataInput in;
std::vector<Data> d;
d.push_back(Data(1000, "ABC"));
d.push_back(Data(2000, "XYZ"));
dataInput.setData(d); // yes setting data
dataInput.printData(); // yes printing
return 0;
}
Do a memcpy of the entire array, just assigning the data might lead to memory leaks due to stack frame removal or deletion. This way however you lose the logging simultaneously avoiding the for loop increasing performance
void DataInput :: setData(const struct Data const* d, const int numberOfData) {
// Cleanup old data!
if(this->data) delete [] this->data;
if(!d) throw new std::invalid_argument("Cannot set NULL data!"); // Remove this line if NULL may be assigned and replace with the commented code.
// if(!d) {
// this->data = NULL;
// this->dataSize = 0;
// } else {
this->data = new Data[(this->dataSize = numberOfData)];
memcpy(this->data, d, sizeof(struct Data) * numberOfData);
// }
}
Don't forget to update the DataInput class!
class DataInput {
public:
int dataSize;
struct Data* data;
DataInput();
virtual ~DataInput();
void setData(const struct Data const* d, const int numberOfData);
void printData();
private:
};
void DataInput::printData() {
for (int i = 0; i< this->dataSize; i++){
printf("name--> %s \n",this->data[i].name);
printf("salary--> %d \n",this->data[i].salary);
}
}
DataInput::~DataInput() {
if(this->data) delete [] this->data;
}