C, Large pointer array allocation (linux 64 bit) - c++

Im allocating 25,000,000,000 units of these :
struct test
{
public:
test();
void insert(unsigned int var1, unsigned int var2, unsigned long var3);
bool isEmpty() const;
unsigned char * data;
};
test::test()
{
data = NULL;
}
bool test::isEmpty() const
{
return (data == NULL);
}
unsigned long index = 25000000000;
like this :
test *something = new (nothrow) test[index];
if (!something)
{
cout << "Error allocating memory for [something]" << endl;
return ;
}
cout << "DONE !" << endl;
then i even made sure its data initialized to NULL.
unsigned long j=0;
while (j<index)
{
something[j].data = NULL;
j++;
}
And its all good, except when i iterate through the something[], like this :
test *chk;
unsigned long empty = 0;
unsigned long not_empty = 0;
unsigned long i=0;
for (i=0; i< index; i++ )
{
chk = &something[i];
if (!chk->isEmpty())
{
not_empty++;
} else
empty++;
}
cout << "Empty [" << empty << "]" << endl;
cout << "Not Empty [" << not_empty << "]" << endl;
cout << "Total [" << empty + not_empty << "]" << endl;
(LAST UPDATE)
It turned out to be hardware problem - memory. Some of sticks were not working properly together with others. Thanks everyone for suggestions and too bad hardware path isnt in answers o/
(UPDATE)
I get constant number of initialized elements that are not NULL (not_empty). Still have no idea why.
Of course, empty + not_empty = index.
If i comment out data = NULL; in constructor function, i get proper empty/not_empty numbers if i loop through array right after allocating it. but still, after forcing pointers to NULL, i get same constant not_empty value, after looping through array again.
I also had this reworked to plain pointers, using malloc(), and it made no difference, except that it was first the time i noticed pointers to be correct (empty) until i set them.
I did some tests with smaller [index] value (5,500,000,000), and i could not replicate the behavior.
Im using google`s ltcmalloc and allocated memory size suggests, it is using correct [index] size;

Rather than 25000000000, write 25000000000ul. I have suspect your number becomes a 32-bit integer, thus the j < 25000000000 is always true as int(25000000000) = -769803776.

Related

Why does creating 2 variables cause a crash in custom STL, C++ VS2019?

Hello I'm trying to rewrite my own memory manager and STL (nothing fancy, just some basic vector and string features) and I'm getting a strange behaviour. I'm trying to get experience in the memory management field because I'm a high school student with time to spare. The problem is, when I create my first variable everything goes perfectly but after creating the second variable, the program crashes while creating the first variable.
String.h/.cpp
class String {
char* pointer_toBuffer = nullptr;
size_t buffer_length = 0;
IAllocator* Allocator;
public:
String(const char* text, IAllocator* Allocator);}
String::String(const char* text, TuranAPI::MemoryManagement::IAllocator* MemoryAllocator) : Allocator(MemoryAllocator) {
std::cout << "String creation has started: " << text << std::endl;
unsigned int i = 0;
while (text[i] != 0) {
i++;
}
buffer_length = i + 1;
pointer_toBuffer = (char*)Allocator->Allocate_MemoryBlock(buffer_length * sizeof(char));//When I write the Second String part, FirstString crashes directly. I use VSDebug and it says access violation here while creating FirstString. It is successful if I delete the SecondString part.
for (unsigned int letterindex = 0; letterindex < i; letterindex++) {
pointer_toBuffer[letterindex] = text[letterindex];
}
pointer_toBuffer[i] = 0;
}
MemoryManagement.h/cpp
TAPIMemoryAllocator::TAPIMemoryAllocator(MemoryBlockInfo MemoryPool_toUse){
std::cout << "TAPIMemoryAllocator is created!\n";
std::cout << "MemoryPool's start pointer: " << MemoryPool_toUse.address << std::endl;
MemoryPool.address = MemoryPool_toUse.address;
MemoryPool.size = MemoryPool_toUse.size;
SELF = this;
}
void* TAPIMemoryAllocator::Allocate_MemoryBlock(size_t size) {
std::cout << "MemoryPool's start pointer: " << MemoryPool.address << std::endl;
std::cout << "A buffer of " << size << " bytes allocation request found in TAPIMemoryAllocator!\n";
if (SELF == nullptr) {
TMemoryManager First(1024 * 1024 * 1024 * 1);
MemoryBlockInfo FirstMemoryBlock;
FirstMemoryBlock.address = SELF->MemoryPool.address;
FirstMemoryBlock.size = size;
Allocated_MemoryBlocks[0] = FirstMemoryBlock;
return (char*)SELF->MemoryPool.address;
}
void* finaladdress = SELF->MemoryPool.address;
for (unsigned int blockindex = 0; blockindex < MAX_MEMORYBLOCKNUMBER; blockindex++) {
MemoryBlockInfo& MemoryBlock = Allocated_MemoryBlocks[blockindex];
finaladdress = (char*)finaladdress + MemoryBlock.size;
if (size <= MemoryBlock.size && MemoryBlock.address == nullptr) {
std::cout << "Intended block's size is less than found memory block!\n";
MemoryBlock.address = finaladdress;
//You shouldn't change Memory Block's size because all of the allocations before this are based upon the previous size!
//You should move all the previous allocated memory to set the size (which is not ideal!)
//If I'd want to find memory leaks causing this, I could write code here to log the leaks!
return MemoryBlock.address;
}
else if (MemoryBlock.size == 0 && MemoryBlock.address == nullptr) {
std::cout << "An empty block is created for intended block! Block's Array index is: " << blockindex << "\n";
std::cout << "MemoryPool's start pointer: " << MemoryPool.address << std::endl << "MemoryBlock's pointer: " << finaladdress << std::endl;
//This means this index in the Allocated_MemoryBlocks has never been used, so we can add the data here!
MemoryBlock.address = finaladdress;
MemoryBlock.size = size;
return MemoryBlock.address;
}
}
//If you arrive here, that means there is no empty memory block in the Allocated_MemoryBlocks array!
std::cout << "There is no empty memory block in the Allocated_MemoryBlocks array, so nullptr is returned!\n";
return nullptr;
}
TMemoryManager::TMemoryManager(size_t Main_MemoryBlockSize) {
if (SELF != nullptr) {
std::cout << "You shouldn't create a MemoryManager!";
return;
}
std::cout << "TMemoryManager is created!\n";
MainMemoryBlock.address = malloc(Main_MemoryBlockSize);
MainMemoryBlock.size = Main_MemoryBlockSize;
SELF = this;
std::cout << "Main Memory Block's start pointer: " << MainMemoryBlock.address << std::endl;
MemoryBlockInfo TuranAPI_MemoryPool;
TuranAPI_MemoryPool.address = MainMemoryBlock.address;
std::cout << "TuranAPI_MemoryPool.address: " << TuranAPI_MemoryPool.address << std::endl;
TuranAPI_MemoryPool.size = 1024 * 1024 * 10;
TAPIMemoryAllocator Create(TuranAPI_MemoryPool);
}
TMemoryManager* TMemoryManager::SELF = nullptr;
TMemoryManager First(1024 * 1024 * 1024 * 1);
Main.cpp
String FirstString("How are you?", TAPIMemoryAllocator::SELF);
std::cout << FirstString << std::endl; //If I delete the below, it prints "How are you?" as expected
String SecondString("I'm fine, thanks!", TAPIMemoryAllocator::SELF);
std::cout << SecondString << std::endl;
Solved: The problem was in Allocator. When allocator goes out of scope, it's Allocate_MemoryBlock function (it's a virtual function, not static) is deleted. I don't know why it doesn't occur when only one String is created (maybe a compiler optimization) but storing Allocator's itself (All of variables was static already) and assinging SELF as stored one's pointer solved the problem.

Issue With Freeing Dynamically Allocated Memory In C++

Before my program can free up memory and end it crashes. Crashes seem to happen on transition from the function UserDataCollection and back to main. This is only my second program using pointers so I'm still quite the newbie considering the whole point of c++ is to use pointers.
Here is the aforementioned code:
#include <iostream>
//Prototypes
void UserDataCollection(int * &movieData_ptr, int &numSurveyed); // Movie Statistics
void DisplayOutput(int *movieData_ptr, int numSurveyed); //Mean, Median, Mode (Display To Console)
//Global Constants
int main()
{
//Variables
int numSurveyed = 0;
//Pointers
int * movieData_ptr = nullptr;
movieData_ptr = new int[numSurveyed];
//"Program Start"
std::cout << "Program start...\n\n";
UserDataCollection(movieData_ptr, numSurveyed);
DisplayOutput(movieData_ptr, numSurveyed);
//Release Memory
delete[] movieData_ptr;
std::cout << "Memory Cleared.";
return 0;
}
void UserDataCollection(int * &movieData_ptr, int &numSurveyed)
{
//Get Number of Students Surveyed
std::cout << "How many students were surveyed: ";
std::cin >> numSurveyed;
//Student Data Input Loop
for (int i = 0; i < numSurveyed; i++)
{
//Get Student Data
std::cout << "Enter How many movies student " << i + 1 << " has seen in ONE month: ";
std::cin >> *(movieData_ptr + i);
//Validation Check
while (*(movieData_ptr + i) >= 337)
{
std::cout << "\nImpossible value!" << std::endl
<< "Hours in a month: 730. Average movie length: 130 minutes."
<< "Total Possible movies: 337";
std::cout << "\n\nEnter How many movies student " << i + 1 << " has seen in ONE month: ";
std::cin >> *(movieData_ptr + i);
} //end while (Validation Check)
} // end for (Data Input)
}
void DisplayOutput(int *movieData_ptr, int numSurveyed)
{
//Display loop for pointer array
for (int i = 0; i < numSurveyed; i++)
{
std::cout << *(movieData_ptr + i) << " ";
}
//End Message
std::cout << "\n\nProgram end.";
}
You never allocated any memory.
int numSurveyed = 0;
//Pointers
int * movieData_ptr = nullptr;
movieData_ptr = new int[numSurveyed];
This is the equivalent of
int *movieData_ptr = new int[0];
You are allocating size of 0 ints. This is undefined behaviour. You can't do anything useful with that pointer without a segmentation fault. You need to either pre-allocate a certain amount, and make sure you don't overflow, or dynamically allocate every time you plan to add data.
Since this is C++, it's probably better not to use raw pointers, but use vector or something instead.
Sorry:
From 5.3.4/7
When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.
From 3.7.3.1/2
The effect of dereferencing a pointer returned as a request for zero size is undefined.

vector of structs with weird behavior c++

i have a problem with one assignment that i have. I have to read a .ts file, read the packets that are inside and extract header information from each packet.
I have created a struct Packet that will hold all the info of the header, and i also have a vector in which i will push_back each Packet.
The problem is that the for loop stops for some reason on the 163rd loop. If i loop until lets say i=160, then the code escapes ends the loop, but when i print the vector.size() i get a really huge number which doesn't make sense. i guess it should be an integer value as high as the pushed back number of Packets.Here is the code that i have so far:
int main() {
FILE *ts_file = NULL;
ts_file = fopen64("/home/ddd/Desktop/Assignment/Streams/ddd.ts", "rb");
if (ts_file == NULL){
cout << "No file detected on this path, try again" << endl; // prints !!!Hello World!!!
}
TS_Analyzer *ts_analyzer;
ts_analyzer->parse_file(ts_file);
cout << "Finished main" << endl;
return 0;
}
void TS_Analyzer::parse_file(FILE *ts_file){
cout << "Inside parser" << endl;
fseek(ts_file,0,SEEK_END);
long file_size = ftell(ts_file);
rewind (ts_file);
number_of_packets = file_size/PACKET_SIZE;
unsigned int current_header_add = 0;
unsigned int i=0;
for (unsigned int j=1; i<number_of_packets; j++)
{
i++;
unsigned char TS_raw_header[4];
cout << "current position " << int(current_header_add) << endl;
current_header_add = ftell(ts_file);
fread(&TS_raw_header, sizeof(TS_raw_header), 1, ts_file);
Packet current_packet;
current_packet.sync_byte = TS_raw_header[0];
current_packet.transport_error_indicator = (TS_raw_header[1] & 0x80) >> 7;
current_packet.payload_start_indicator = (TS_raw_header[1] & 0x40) >> 6;
current_packet.transport_priority = (TS_raw_header[1] & 0x20) >> 5;
current_packet.PID = ((TS_raw_header[1] & 31) << 8) | TS_raw_header[2];
current_packet.transport_scrambling_control = (TS_raw_header[3] & 0xC0);
current_packet.adaption_field_control = (TS_raw_header[3] & 0x30) >> 4;
current_packet.continuity_counter = (TS_raw_header[3] & 0xF);
stream_packets.push_back(current_packet);
//cout << hex << int(current_packet.PID) << endl;
//cout << dec << "continuity counter " << int(current_packet.continuity_counter) << endl;
cout << " i " << int(i) << endl;
fseek(ts_file, 184, SEEK_CUR);
}
cout << "##" << endl;
cout << stream_packets.size() << endl;
}
class TS_Analyzer: public Analyzer {
public:
TS_Analyzer();
~TS_Analyzer();
struct Packet {
unsigned char sync_byte;
unsigned char transport_error_indicator;
unsigned char payload_start_indicator;
unsigned char transport_priority;
unsigned int PID;
unsigned char transport_scrambling_control;
unsigned char adaption_field_control;
unsigned char continuity_counter;
};
std::vector<Packet>stream_packets;
int number_of_packets = 0;
void parse_file(FILE *);
};
Any ideas of why the vector push_back breaks the for loop and why i cannot get a correct vector size?
If I put this code through the clang compiler, I get an error on following code:
TS_Analyzer *ts_analyzer;
ts_analyzer->parse_file(ts_file);
>> variable 'ts_analyzer' is uninitialized when used here
I guess you are encountering undefined behavior: As ts_analyzer as ptr is any random value, the data in its members is also very random.
I'm actually surprised that this code runs at all without crashing, though you can always be lucky.
If you like to fix this, try avoiding pointers by creating the object at the stack:
TS_Analyzer ts_analyzer;
ts_analyzer.parse_file(ts_file);
or if you really need allocated memory, at least fill in the pointer:
auto ts_analyzer = std::make_unique<TS_Analyzer>();
ts_analyzer->parse_file(ts_file);

Issue in reading repeated fields from protocol buffers in C++

org.proto
message Optimize {
required int element_size = 1;
required string element_name = 2;
}
message nodes {
repeated Optimize = 1;
}
Have this decoding function:
DecodeNodeMsg(char *msg, int size)
{
Org::nodes node;
int element_size;
string element_name;
int NumofElem = 0;
node.ParseFromArray((void *)msg, size);
for (int i = 0; i < nodes.Optimize().size(); i++)
{
element_size = nodes.Optimize(i).element_size();
element_name = nodes.Optimize(i).element_name();
cout << "size" << element_size << endl;
cout << "name" << element_name << endl;
NumofElem++;
}
cout << "number of" << NumofElem << endl;
}
I am encoding a nodes message with three Optimize messages in it. and calling this decode function. Encoding part is an old code which is working fine from long time. So i dont suspect the encoding function.
In the decode function, I see that the NumofElem is correctly printed as three. However, i see that both element_size & element_name are just garbage. Integer has some junk value and string has a binary data.
I am having this issue only if this repeated fields. If fields are required/optional fields, then i dont have this issue.
Could some one has similar issue... ? if so any clues on how to fix this ?
Thanks,
Kiran
I don't see where you are actually decoding a message. I see you creating a new node object, but then calling Org::nodes() which looks wrong. I think you need to access the Optimize elements like this:
for (int i = 0; i < node->optimize_size(); i++)
{
element_size = node->optimize(i).element_size();
element_name = node->optimize(i).element_name();
cout << "size" << element_size << endl;
cout << "name" << element_name << endl;
NumofElem++;
}
But again I think your nodes object needs to be decoded from something. The mutable methods allow you to set data. There's also the ParseFrom methods. Also in my proto files I number the elements in a message. See https://developers.google.com/protocol-buffers/docs/overview
message nodes {
repeated Optimize = 1;
}
The function deserializes the buffer into the local variable node, but the loop references nodes. I'd also validate the return value from ParseFromArray.

Converting and Passing Arrays

I basically want to pass this array of data I'm reading to diffent functions and eventually plot it.
The array contains a 32 bit word of '1's and '0's, I then want to add these individual bits together to see where my data spikes. So in other words if I add "0100" to "0110" I get "0210" - which is probably easier done with separate bins and plotting.
At the moment I'm just getting garbage out.
void binary(int convert, int* dat) {
bitset<32> bits(convert);
//cout << bits.to_string() << endl;
char data[32];
for(unsigned i = 0; i < 32; ++i) {
data[i] = bits[i];
}
for(unsigned i = 32; i; --i) {
dat[i] = (int(data[i-1]))+dat[i];
}
}
void SerDi() {
int dat[32];
cout << " Reading data from memory..." << endl;
ValVector< uint32_t> data=hw.getNode("SerDi.RAM").readBlock(8);
hw.dispatch();
cout << data[0]<<endl;
cout << data[1]<<endl;
for (unsigned i = 2; i < 7; i++) {
binary(data[i], dat);
}
cout << dat[7] << endl;
graph(dat); //passes the array to a place where I can plot the graph
}
You have
int dat[32];
But in convert you have i = 32 and dat[i] That will access something outside of the array and bad things will happen.
Also that is not initialized. Add a memset/loop somewhere to make dat initially 0.