Struct containing vector of pointers to other structs - c++

I have a little complicated data structure but I have a problem with insertion to it, maybe I am thinking wrong.
This data structure is something like (we have a map which is a pair of uint16_t and structure, and three nested structures)
struct Struct4
{
uint8_t struct4ByteData1;
uint8_t struct4ByteData2;
uint16_t struct4ShortIntData1;
uint16_t struct4ShortIntData2;
};
struct Struct3
{
uint32_t struct3IntData1;
uint16_t struct3ShortIntData1;
uint16_t numOfElementsInVectorOfStruct4;
std::string struct3StringData;
std::vector<std::shared_ptr<Struct4>> struct4vector;
};
struct Struct2
{
uint32_t struct2IntData1;
uint16_t struct2ShortIntData1;
uint16_t numOfElementsInVectorOfStruct3;
int16_t struct2ShortIntData2;
std::string struct2StringData;
std::vector<std::shared_ptr<Struct3>> struct3vector;
};
struct Struct1
{
uint32_t struct1IntData1;
uint16_t numOfElementsInVectorOfStruct2;
std::vector<std::shared_ptr<Struct2>> struct2vector;
};
using uint16AndStruct1Map = std::multimap<uint16_t, Struct1>;
And here is a code snippet how data is inserted:
Struct1* struct1_ptr = new Struct1;
std::shared_ptr<Struct2> vectorOfStruct2;
std::shared_ptr<Struct3> vectorOfStruct3;
std::shared_ptr<Struct4> vectorOfStruct4;
uint16AndStruct1Map mapToBeInserted;
bool validData = false;
uint16_t numOfElementsInVectorOfStruct4;
uint16_t status;
uint16_t keyDataFromStruct2;
struct1_ptr->struct1IntData1 = getSomeData();
struct1_ptr->numOfElementsInVectorOfStruct2 = getSomeElements();
if (struct1_ptr->numOfElementsInVectorOfStruct2 == 0)
{
std::cout << "No Pim Avoidance Measurement in This Message, ignore" << std::endl;
return;
}
for(uint16_t i = 0; i < getNumOfElementsOfStruct2(); i++)
{
vectorOfStruct2 = std::make_shared<vectorOfStruct2>();
keyDataFromStruct2 = getKey();
vectorOfStruct2->struct2IntData1 = getSomeData();
vectorOfStruct2->struct2ShortIntData1 = keyDataFromStruct2;
vectorOfStruct2->struct2ShortIntData2 = getSomeData();
vectorOfStruct2->numOfElementsInVectorOfStruct3 = getSomeElements();
vectorOfStruct2->struct2StringData = getSomeStringData();
struct1_ptr->struct2vector.push_back(vectorOfStruct2);
for(uint16_t j = 0; j < getNumOfElementsOfStruct3(); j++)
{
vectorOfStruct3 = std::make_shared<vectorOfStruct3>();
vectorOfStruct3->struct3IntData1 = getSomeData();
vectorOfStruct3->struct3ShortIntData1 = getSomeData();
vectorOfStruct3->numOfElementsInVectorOfStruct4 = getSomeElements();
vectorOfStruct3->struct3StringData = getSomeStringData();
struct1_ptr->struct2vector[i]->struct3vector.push_back(vectorOfStruct3);
numOfElementsInVectorOfStruct4 = getNumOfElementsOfStruct4();
if(numOfElementsInVectorOfStruct4 < 10)
{
for(uint16_t k = 0; k < numOfElementsInVectorOfStruct4; k++)
{
vectorOfStruct4 = std::make_shared<vectorOfStruct4>();
status = getStatus();
if(status == SPECIAL_STATUS_TO_GET_INSIDE_THIS_IF_COND)
{
vectorOfStruct4->struct4ByteData1 = getSomeData();
vectorOfStruct4->struct4ByteData2 = getSomeData();
vectorOfStruct4->struct4ShortIntData1 = getSomeData();
vectorOfStruct4->struct4ShortIntData2 = status;
struct1_ptr->struct2vector[i]->struct3vector->struct4vector.push_back(vectorOfStruct4);
validData = true;
}
}
}
}
if(validData)
{
mapToBeInserted.insert (std::make_pair(keyDataFromStruct2,*struct1_ptr));
}
else
{
for (auto it = mapToBeInserted.begin(); it!=mapToBeInserted.end(); it++)
{
it->second.numOfElementsInVectorOfStruct2--;
}
}
validData = false;
}
After everything was inserted into map (and all of structures), when I want to get data from this map I probably get memory error. I am not 100% sure what the problem is.
The issue occurs at level of obtaining data from the map: mapToBeInserted.
Could you help?

if numOfElementsInVectorOfStruct4 is more than 10 you don't insert anything into struct4vector therefore this loop will access out of the bounds of struct4vector:
for(uint16_t l = 0; l < kv.second.struct2vector[j]->struct3vector[k]->numOfElementsInVectorOfStruct4; l++)
{
ss << "<"
<< kv.second.struct2vector[j]->struct3vector[k]->struct4vector[l]->struct4ByteData1 << ","

There are nothing wrong with the map insertion. The program crashed because of the vector index numOfElementsInVectorOfStruct4.
You have set the number of element :
vectorOfStruct3->numOfElementsInVectorOfStruct4 = getSomeElements();
But the data of struct4vector is inserted with CONDITION (there are two : < 10 and Status is OK)
So that the vector size struct4vector.size() and numOfElementsInVectorOfStruct4 can be different (when numOfElementsInVectorOfStruct4 < 10 and
one of its element has status OK).
Here are some advices :
Work with pointer (with map) to avoid the struct element copy
Work with vector size() function instead of getSomeElements() somewhere.
Check for the map element exists before used

Related

Dynamic array of structs containing a dynamic array of structs

I can't for the life of me figure out how to solve this in c.
I have the following structs:
typedef struct
{
uint8_t index = 0;
DLPageItem_t *pageItems = NULL;
uint8_t pageItemCount = 0;
uint8_t selectedItemIndex = 0;
} DLPage_t;
typedef struct
{
uint8_t index = 0;
void *valuePtr = NULL;
uint16_t tmpValue = 0;
DLItemType_t type = DLITEMTYPE::NOTYPE;
uint8_t row = 0;
uint8_t col = 0;
uint8_t targetPageId = 0;
DLItemAction_t action = DLITEMACTION::EDIT;
bool selectable = false;
bool editing = false;
} DLPageItem_t;
And I want to have a dynamic array of DLPage_t (with realloc) and then be able to anytime add DLPageItem_t to any of the already created DLPage_t array members.
So I tried to have a
DLPage_t *_pages = NULL;
and do
this->_pageCount++;
this->_pages = (DLPage_t*)realloc(this->_pages, this->_pageCount * sizeof(DLPage_t));
Then I'm accessing the "pages" and setting the values like this:
this->_pages[this->_pageCount - 1].index = this->_pageCount - 1;
The function which adds DLPageItem_t structs to a DLPage_t struct member, I do it like this:
this->_pages[pageId].pageItemCount++;
this->_pages[pageId].pageItems = (DLPageItem_t*)realloc(this->_pages[pageId].pageItems, this->_pages[pageId].pageItemCount * sizeof(DLPageItem_t));
I have some very funny business going on so I guess I'm doing something wrong and accessing/overwriting memory where I shouldn't.
Can someone please verify whether what I'm doing is correct? I tried to apply/adapt this to my issue but I just can't figure it out: https://stackoverflow.com/a/15397992
Thanks!

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.

C++ Calculating Shortest Path in a Directed Graph

I am tasked with writing a program to maintain the representation of a simple network(weighted directed graph) and compute the best path between two given nodes upon request.
Currently, I am attempting to write a function to compute the simplest between two nodes, however, when attempting to run my program, I get two specific error
Severity Code Description Project File Line Suppression State
Error C3863 array type 'bool [openNode]' is not assignable P 127
and
Severity Code Description Project File Line Suppression State
Error C3863 array type 'int [openNode]' is not assignable
I am unable to debug since these two primary errors are not allowing my program to run. Is there any particular reason for these errors?
Thanks in advance!
This is the node structure defined in Graph.h
struct GraphNode
{
char ID;
std::string name;
int inNodes = 0;
int outNodes = 0;
std::vector<std::pair<GraphNode*, int>> connection;
int connections = 0;
};
And here is the particular code that causes the errors.
#include "Graph.h"
std::vector<GraphNode*> _graph;
int openNode = 0;
//Obligatory constructor
void Graph()
{
}
void shortestPath(char fromNode, char toNode)
{
bool known[openNode];
int distance[openNode];
GraphNode* previous[openNode];
int numbChecked = 0;
for (int i = 0; i < openNode; i++)
{
known[i] = false;
distance[i] = 999999;
previous[i] = nullptr;
}
distance[findNode(fromNode)] = 0;
while (numbChecked < openNode)
{
int smallestUnknown = 9999999;
int locationOfSmall = 0;
for (int i = 0; i < openNode; i++)
{
if (known[i] == false && distance[i] < smallestUnknown)
{
smallestUnknown = distance[i];
locationOfSmall = i;
}
}
if (distance[locationOfSmall] == 0)
{
previous[locationOfSmall] = nullptr;
}
known[locationOfSmall] = true;
numbChecked++;
if (_graph[locationOfSmall]->outNodes > 0)
{
for (int i = 0; i < _graph[locationOfSmall]->outNodes; i++)
{
int newDistanceLocation = findNode(_graph[locationOfSmall]->connection[i].first->ID);
if (known[newDistanceLocation] == false && (distance[locationOfSmall] + _graph[locationOfSmall]->connection[i].second) < distance[newDistanceLocation])
{
distance[newDistanceLocation] = distance[locationOfSmall] + _graph[locationOfSmall]->connection[i].second;
previous[newDistanceLocation] = _graph[locationOfSmall];
}
}
}
}
int destination = findNode(toNode);
std::string output;
std::string charTransfer;
charTransfer = toNode;
output = charTransfer;
while (previous[destination] != nullptr)
{
destination = findNode(previous[destination]->ID);
charTransfer = _graph[destination]->ID;
output = charTransfer + "->" + output;
}
if (_graph[destination]->ID != fromNode)
{
std::cout << "The nodes are not connected." << std::endl;
}
else
{
std::cout << "The path is: " << output << std::endl;
std::cout << "The distance is: " << distance[findNode(toNode)] << std::endl;
}
}
Any change suggestions would be much appreciated!
You have invalid code at the beginning of your shortestPath function:
bool known[openNode];
int distance[openNode];
GraphNode* previous[openNode];
You cannot use variables to create arrays on the stack (which is what you are trying to do there), because the compiler doesn't know the value of openNode at compile time (which is needed to determine the stack size).
Why don't you use a vector, like:
std::vector<bool> known(openNode, false);
std::vector<int> distance(openNode, 999999);
std::vector<GraphNode*> previous(openNode, nullptr);
Using this method makes the for loop below obsolete aswell.

Why does random extra code improve performance?

Struct Node {
Node *N[SIZE];
int value;
};
struct Trie {
Node *root;
Node* findNode(Key *key) {
Node *C = &root;
char u;
while (1) {
u = key->next();
if (u < 0) return C;
// if (C->N[0] == C->N[0]); // this line will speed up execution significantly
C = C->N[u];
if (C == 0) return 0;
}
}
void addNode(Key *key, int value){...};
};
In this implementation of Prefix Tree (aka Trie) I found out that 90% of findNode() execution time is taken by a single operation C=C->N[u];
In my attempt to speed up this code, I randomly added the line that is commented in the snipped above, and code became 30% faster! Why is that?
UPDATE
Here is complete program.
#include "stdio.h"
#include "sys/time.h"
long time1000() {
timeval val;
gettimeofday(&val, 0);
val.tv_sec &= 0xffff;
return val.tv_sec * 1000 + val.tv_usec / 1000;
}
struct BitScanner {
void *p;
int count, pos;
BitScanner (void *p, int count) {
this->p = p;
this->count = count;
pos = 0;
}
int next() {
int bpos = pos >> 1;
if (bpos >= count) return -1;
unsigned char b = ((unsigned char*)p)[bpos];
if (pos++ & 1) return (b >>= 4);
return b & 0xf;
}
};
struct Node {
Node *N[16];
__int64_t value;
Node() : N(), value(-1) { }
};
struct Trie16 {
Node root;
bool add(void *key, int count, __int64_t value) {
Node *C = &root;
BitScanner B(key, count);
while (true) {
int u = B.next();
if (u < 0) {
if (C->value == -1) {
C->value = value;
return true; // value added
}
C->value = value;
return false; // value replaced
}
Node *Q = C->N[u];
if (Q) {
C = Q;
} else {
C = C->N[u] = new Node;
}
}
}
Node* findNode(void *key, int count) {
Node *C = &root;
BitScanner B(key, count);
while (true) {
char u = B.next();
if (u < 0) return C;
// if (C->N[0] == C->N[1]);
C = C->N[0+u];
if (C == 0) return 0;
}
}
};
int main() {
int T = time1000();
Trie16 trie;
__int64_t STEPS = 100000, STEP = 500000000, key;
key = 0;
for (int i = 0; i < STEPS; i++) {
key += STEP;
bool ok = trie.add(&key, 8, key+222);
}
printf("insert time:%i\n",time1000() - T); T = time1000();
int err = 0;
key = 0;
for (int i = 0; i < STEPS; i++) {
key += STEP;
Node *N = trie.findNode(&key, 8);
if (N==0 || N->value != key+222) err++;
}
printf("find time:%i\n",time1000() - T); T = time1000();
printf("errors:%i\n", err);
}
This is largely a guess but from what I read about CPU data prefetcher it would only prefetch if it sees multiple access to the same memory location and that access matches prefetch triggers, for example looks like scanning. In your case if there is only single access to C->N the prefetcher would not be interested, however if there are multiple and it can predict that the later access is further into the same bit of memory that can make it to prefetch more than one cache line.
If the above was happening then C->N[u] would not have to wait for memory to arrive from RAM therefore would be faster.
It looks like what you are doing is preventing processor stalls by delaying the execution of code until the data is available locally.
Doing it this way is very error prone unlikely to continue working consistently. The better way is to get the compiler to do this. By default most compilers generate code for a generic processor family. BUT if you look at the available flags you can usually find flags for specifying your specific processor so it can generate more specific code (like pre-fetches and stall code).
See: GCC: how is march different from mtune? the second answer goes into some detail: https://stackoverflow.com/a/23267520/14065
Since each write operation is costly than the read.
Here If you see that,
C = C->N[u]; it means CPU is executing write in each iteration for the variable C.
But when you perform if (C->N[0] == C->N[1]) dummy++; write on dummy is executed only if C->N[0] == C->N[1]. So you have save many write instructions of CPU by using if condition.

Inserting values of an map with vectors

I have the following map:
std::map<u_long, std::vector<CChatContainer*> >m_Container;
class CChatContainer
{
public:
CChatContainer()
{
m_uStartPos = 0;
m_uEndPos = 0;
m_dwColor = NULL;
m_pItemElem = NULL;
}
~CChatContainer(){};
u_long m_uStartPos;
u_long m_uEndPos;
DWORD m_dwColor;
void* m_pItemElem;
};
how do I insert values in it, the vector part seems very complex to me
Example:
u_long j = 2; // get index in the map - where to insert
std::vector<CChatContainer*> conts; // create container to insert
for( int i = 0; i < N; i++ ) { // fill the container
CChatContainer* new_cont = new CChatContainer;
cont.push_back(new_cont);
}
m_Container[j] = conts; // insert