Can not delete char pointer in C++ - c++

Why can not I perform the following line?
delete [] target;
in my case?
Here is the code:
main.cpp
#include <iostream>
using namespace std;
#include "Char.h"
int main()
{
char * text = "qwerty";
char * a = new char[charlen(text)+1];
copyon(a,text);
cout<<a<<endl;
char * test = "asdfghjkl";
assign(&a, test);
assign(&a, a);
char * test1 = new char[26];
for (int i(0); i < 26; i++)
{
test1[i] = char(i+65);
}
test1[26] = '\0';
anotherAssign(test1, a);
cout << test1 << endl;
return 0;
}
Char.cpp
#include "Char.h"
#include <iostream>
#include <cassert>
#include <cstring>
size_t charlen(const char * ps)
{
size_t len=0;
while (ps[len++]);
assert(len-1==strlen(ps));
return len;
}
void assign(char** target, const char* source)
{
if (*target==source)
return;
delete [] *target;
*target = new char[charlen(source)+1];
copyon(*target, source);
return;
}
void anotherAssign(char* target, const char* source)
{
if (target==source)
return;
delete [] target;
target = new char[charlen(source)+1];
copyon(target, source);
return;
}
void copyon(char* const target, const char* const source)
{
char * t = target;
const char * s = source;
while (*t++ = *s++);
//while(*target++ = *source++)
// ;
std::cout << target << " source = " << source << std::endl;
return;
size_t len = charlen(source);
//for (size_t i=0; i<len; ++i)
// target[i]=source[i];
//target[len]='\0';
}
Here is an exception:

If you do:
char * test1 = new char[26];
then your array will go from test1[0] to test1[25].
That means:
test1[26] = '\0';
is out of bounds. At this point, the head is corrupted, and what happens next is undefined (but rarely desirable).

Related

.exe file has triggered a breakpoint

I am writing a list-based multi-stack program. At first everything worked fine. Then I added a few exceptions. After that, the program began to build normally, but after throwing an exception, the program breaks. I opened the debugger and reached the place of error. There I found a place where another exception is thrown. But all that was written there is "MultiListStack.exe has triggered a breakpoint.". Please tell me, because of what it can be and how to fix it? Below I attach the code:
tmultiroot.h
//tmultiroot.h
//base abstract class for inheritance
#ifndef __MULTROOT_H__
#define __MULTROOT_H__
const int MemLimit = 4; // memory size
const int StackNum = 2; // number of stacks
typedef int TElem; // type of element
class TMultiRoot:
{
protected:
TElem Mem[MemLimit]; // memory for stacks (int array of MemLimit elements)
int DefaultStack; // current stack number
public:
TMultiRoot() { DefaultStack = 0; }
virtual bool IsEmpty(int ns) const = 0; // void control
virtual bool IsFull (int ns) const = 0; // overflow control
virtual void Put (int ns, const TData &Val) = 0; // put on the stack
virtual TData Get (int ns) = 0; // take from stack with deletion
// methods for working with the current stack
void SetDefaultStack(int ns) { DefaultStack = ns; } //current stack
int IsEmpty(void) const { return IsEmpty(DefaultStack); } // empty?
int IsFull(void) const { return IsFull (DefaultStack); } // full of?
void Put(const TData &Val) { Put(DefaultStack, Val); } // in the stack
TData Get(void) { return Get(DefaultStack); } // from the stack
};
#endif
multiliststack.h
//multiliststack.h
#ifndef __MULTILISTSTACK_H__
#define __MULTILISTSTACK_H__
#include "tmultiroot.h"
typedef int TElem; // type of element
class TMultiListStack: public TMultiRoot
{
protected:
int NextLink[MemLimit]; // next link index
int StackInd[StackNum]; // stack top index
int FirstFreeLink; // first free link index
public:
TMultiListStack();
virtual bool IsEmpty(int ns) const; // void control
virtual bool IsFull (int ns) const; // overflow control
virtual void Put (int ns, const TData &Val); // put on the stack
virtual TData Get (int ns); // take from stack with deletion
// utility methods
void Print(); // print stack values
int IsValid() { return 0; } // structure testing
};
#endif
exceptions.h
//exceptions.h
#ifndef _exceptions_h
#define _exceptions_h
//Exception class
class Exception{
protected:
int Line;
char* File;
char* Func;
char* Desc;
public:
Exception() {};//default constructor
Exception(int _Line, char* _File, char* _Func, char* _Desc); //constructor
Exception(const Exception& e); //copy constructor
~Exception(); //destructor
virtual void debug_print(); //display error message
virtual char* GetDesc(); //return error message
};
//stack exception class
class StackExc: public Exception {
protected:
int exc;//exception code, 0 - nomem, 1 - empty, 2 - full
public:
StackExc() {};//default constructor
StackExc(int _Line, char* _File, char* _Func, char* _Desc, int exc); //constructor
StackExc::~StackExc(); //destructor
int GetExc(); //get exception code
virtual void debug_print(); //display error message
};
#endif
ecxeptions.cpp
//exceptions.cpp
#include <cstring>
#include <iostream>
#include "exceptions.h"
//Exception class
Exception::Exception(int _Line, char* _File, char* _Func, char* _Desc) {
Line = _Line;
int size = strlen(_File) + 1;
File = new char[size];
strcpy(File, _File);
Func = new char[size];
strcpy(Func, _Func);
Desc = new char[size];
strcpy(Desc, _Desc);
}
//copy constructor
Exception::Exception(const Exception& e) {
Line = e.Line;
int size = strlen(e.File) + 1;
File = new char[size];
strcpy(File, e.File);
Func = new char[size];
strcpy(Func, e.Func);
Desc = new char[size];
strcpy(Desc, e.Desc);
}
//destructor
Exception::~Exception() {
delete[] File;
delete[] Func;
delete[] Desc;
}
//display exception
void Exception::debug_print() {
std::cerr << Line << " " << File << " " << Func << " " << Desc << std::endl;
}
char * Exception::GetDesc()
{
return Desc;
}
//stack exception class
StackExc::StackExc(int _Line, char* _File, char* _Func, char* _Desc, int exc)
: Exception(_Line, _File, _Func, _Desc), exc(exc) {
}
//destructor
StackExc::~StackExc() {
delete[] File;
delete[] Func;
delete[] Desc;
}
int StackExc::GetExc() {
return exc;
}
//display exception
void StackExc::debug_print() {
std::cerr << Desc << std::endl;
}
multiliststack.cpp
//multiliststack.cpp
#include <stdio.h>
#include "tmultiliststack.h"
#include "exceptions.cpp"
TMultiListStack::TMultiListStack()
{
for (int i = 0; i < MemLimit; i++)
NextLink[i] = i + 1;
NextLink[MemLimit - 1] = -1;
FirstFreeLink = 0;
for (int i = 0; i < StackNum; i++)
StackInd[i] = -1;
}
bool TMultiListStack::IsEmpty(int ns) const // void control
{
return StackInd[ns] < 0;
}
bool TMultiListStack::IsFull(int ns) const // overflow control
{
return FirstFreeLink < 0;
}
void TMultiListStack::Put(int ns, const TData &Val) // put on the stack
{
if (IsFull(ns)) {
throw StackExc(__LINE__, __FILE__, __FUNCTION__, "DataFull", 2); //after throwing this exception
} //it is being processed in main
else // And then an exception "MultiListStack.exe has triggered a breakpoint." occurs on this line
{
int k = FirstFreeLink;
FirstFreeLink = NextLink[k];
Mem[k] = Val;
NextLink[k] = StackInd[ns];
StackInd[ns] = k;
}
}
TData TMultiListStack::Get(int ns) // take from stack with deletion
{
TData temp = -1;
if (IsEmpty(ns))
throw StackExc(__LINE__, __FILE__, __FUNCTION__, "DataEmpty", 1);
else
{
int k = StackInd[ns];
temp = Mem[k];
StackInd[ns] = NextLink[k];
NextLink[k] = FirstFreeLink;
FirstFreeLink = k;
}
return temp;
}
void TMultiListStack::Print() // print stack values
{
int pind, ind, k;
for (int ns = 0; ns < StackNum; ns++)
{
printf("ns=%d -> ", ns);
pind = -1;
ind = StackInd[ns];
while (ind > -1) // pointer wrapping
{
k = NextLink[ind];
NextLink[ind] = pind;
pind = ind;
ind = k;
}
ind = pind;
pind = -1;
while (ind > -1) // pointer recovery and printing
{
printf("%d ", Mem[ind]);
k = NextLink[ind];
NextLink[ind] = pind;
pind = ind;
ind = k;
}
printf("\n");
}
}
main.cpp
#include <windows.h>
#include <conio.h>
#include <iostream>
#include "tmultiliststack.h"
using namespace std;
void main()
{
TMultiListStack mst;
int ms = 2, ns, code, temp, val = 0;
setlocale(LC_ALL, "Russian");
srand(1);
cout << "System Testing N Stacks" << endl;
while (1)
{
try {
val++;
code = random(4); // operation
ns = random(ms); // stack number
Sleep(1000);
if (code < 3) {
cout << "Put " << val << " in " << ns << endl;
mst.Put(ns, val);
mst.Print();
}
else {
cout << "Get from " << ns << endl;
temp = mst.Get(ns);
mst.Print();
}
}
catch (StackExc exc) {
exc.debug_print();
}
if (_kbhit())
break;
}
cout << "Stack Printing" << endl;
mst.Print();
}
When the program starts, 4 values ​​are put on the zero stack. But at the fifth iteration, when the fifth value is to be added to the zero stack, overflow occurs. Because of this, my exception is thrown. Then it is processed in main. And after that, this incomprehensible exception is thrown. No details about it are displayed, so I don’t understand what to do. Tell me, please, how to fix it?

Assigment and adding operator overloading (concatenation of 2 tables and int)

I'm trying to concatenate two arrays and at the end concatenate int, for example: result = arg + arg + 2;
I'm getting "read access violation" at + operator overloading.
I wrote the error and warning in comments below.
My code:
Main:
#include <iostream>
#include <string>
#include "CTable.h"
int main() {
CTable c_tab1, c_tab0;
c_tab0.SetNewSize(3);
c_tab1.SetNewSize(2);
c_tab0.SetValueAt(0, 22);
c_tab0.SetValueAt(1, 23);
c_tab0.SetValueAt(2, 24);
c_tab0.Print();
c_tab1.SetValueAt(0, 31);
c_tab1.SetValueAt(1, 32);
c_tab1.Print();
CTable c_tab3 = (c_tab0 + c_tab1 + 111);
c_tab3.Print();
return 0;
}
Class CTable:
#include <iostream>
#include <string>
using namespace std;
class CTable {
public:
CTable();
CTable(string sName, int iTableLen);
CTable(const CTable& pcOther);
CTable* pcClone();
~CTable();
void ShowName();
void ShowSize();
void SetName(string sName);
bool SetNewSize(int iTableLen);
void SetValueAt(int iOffset, int iNewVal);
void Print();
CTable& operator+(const CTable& pcNewTable);
CTable operator+(int iNewVal) const;
CTable& operator=(const CTable& pcNewVal) {
if (this != &pcNewVal) {
for (int i = 0; i < i_size; i++) {
this->piTable[i] = pcNewVal.piTable[i];
}
}
return *this;
}
private:
string s_name;
int i_size;
int* piTable;
const int SIZE = 10;
const string NAME = "Name";
};
#include <iostream>
#include <string>
#include "CTable.h"
#include <algorithm>
using namespace std;
CTable::CTable() {
s_name = NAME;
cout << "bezp: " << s_name << endl;
piTable = new int[SIZE];
i_size = SIZE;
}
CTable::CTable(string sName, int iTableLen) {
s_name = sName;
cout << "parametr: " << sName << endl;
piTable = new int[iTableLen];
i_size = iTableLen;
}
CTable::CTable(const CTable& pcOther) {
s_name = pcOther.s_name + "copied";
piTable = new int[pcOther.i_size];
i_size = pcOther.i_size;
for (int i = 0; i < pcOther.i_size; i++) {
piTable[i] = pcOther.piTable[i];
}
}
CTable::~CTable() {
delete[] piTable;
}
void CTable::SetName(string sName) {
s_name = sName;
}
bool CTable::SetNewSize(int iTableLen) {
if (iTableLen <= 0) {
cout << "Length has to be greater than 0" << endl;
return false;
}
int* pi_newTable = new int[iTableLen];
for (int i = 0; i < iTableLen; i++) {
pi_newTable[i] = piTable[i];
}
delete this->piTable;
this->i_size = iTableLen;
this->piTable = pi_newTable;
return true;
}
CTable* CTable::pcClone() {
CTable* ct = new CTable(s_name, i_size);
return ct;
}
void CTable::ShowName() {
cout << "Name: " << s_name << endl;
}
void CTable::ShowSize() {
cout << "Size: " << i_size << endl;
}
void CTable::SetValueAt(int iOffset, int iNewVal) {
if (iOffset >= this->i_size) {
return;
}
piTable[iOffset] = iNewVal;
}
void CTable::Print() {
for (int i = 0; i < i_size; i++) {
cout << piTable[i] << " ";
}
cout << endl;
}
CTable& CTable::operator+(const CTable& pcNewTable) {
CTable result("new_int", this->i_size);
result.i_size = (i_size + pcNewTable.i_size);
result.piTable = new int[i_size + pcNewTable.i_size];
for (int i = 0; i < i_size; i++) {
result.piTable[i] = piTable[i];
}
for (int i = 0; i < (pcNewTable.i_size); i++) {
result.piTable[i+i_size] = pcNewTable.piTable[i];
}
return result; //Warning C4172 returning address of local variable or temporary: result
}
CTable CTable::operator+(int iNewVal) const {
CTable result("new_int", this->i_size);
result.i_size = (i_size + 1);
result.piTable = new int[i_size + 1];
for (int i = 0; i < i_size; i++) {
result.piTable[i] = piTable[i]; //Exception thrown: read access violation. **this->piTable** was 0x1110122.
}
result.piTable[i_size + 1] = iNewVal;
return result;
}
What should I correct? I'm not sure about assigment operator overload, is it okay?
The member function SetNewSize has undefined behavior. In this loop
int* pi_newTable = new int[iTableLen];
for (int i = 0; i < iTableLen; i++) {
pi_newTable[i] = piTable[i];
}
it 1) uses uninitialized values because the array was not initialized and 2) iTableLen can be gretaer than the current value of i_size. You should at least zero initialize the array in constructors.
The copy assignment operator aslo has undefined behabior because the number of elements of the array of the object pcNewVal can be less than the number of elements of the array in the assigned object.
The first overloaded operator + also have undefined behavior. For starters as the warning says the operator returns reference to the local object result that will not be alive after exiting the operator. Secondly, there is a memory leak necause the array of the object is allocated anew and the previuous allocated memory in the constructor is not freed.
CTable result("new_int", this->i_size);
result.i_size = (i_size + pcNewTable.i_size);
result.piTable = new int[i_size + pcNewTable.i_size];
//...
The second overloaded operator + also has undefined behavior. As in the previous operator there is a memory leak.
In this statement
result.piTable[i_size + 1] = iNewVal;
there is an access memory outside the allocated array. There should be
result.piTable[i_size] = iNewVal;

Error C2440: 'initializing': cannot convert from 'CTable' to 'CTable'

Honestly, I have no idea why CTable cannot convert to CTable? I'm trying to make overload operator + which returns concatenated two tables.
Error C2440 'initializing': cannot convert from 'CTable' to 'CTable'
Second error: Error (active) E0334 class "CTable" has no suitable copy constructor
#include <iostream>
#include <string>
#include "CTable.h"
int main() {
CTable c_tab_1, c_tab_0;
c_tab_0.vSetValueAt(0, 1);
c_tab_0.vPrint();
c_tab_0.bSetNewSize(4);
c_tab_0.vPrint();
c_tab_1.bSetNewSize(4);
c_tab_0.vSetValueAt(0, 1);
c_tab_0.vSetValueAt(1, 2);
c_tab_0.vSetValueAt(2, 3);
c_tab_0.vSetValueAt(3, 4);
c_tab_0.vPrint();
c_tab_1.vSetValueAt(0, 2);
c_tab_1.vSetValueAt(1, 3);
c_tab_1.vSetValueAt(2, 4);
c_tab_1.vSetValueAt(3, 5);
c_tab_1.vPrint();
c_tab_1.vSetValueAt(2, 123);
c_tab_0.vPrint();
c_tab_1.vPrint();
CTable c_tab_3 = c_tab_0 + c_tab_1; //Error C2440! <-----------------------
c_tab_3.vPrint();
return 0;
}
#include <iostream>
#include <string>
using namespace std;
class CTable {
public:
CTable();
CTable(CTable& pcOther);
CTable* pcClone();
~CTable();
bool bSetNewSize(int iTableLen);
void vSetValueAt(int iOffset, int iNewVal);
void vPrint();
CTable operator+(const CTable& pcNewTable);
private:
string s_name;
int i_size;
int* piTable;
const int SIZE = 10;
const string NAME = "Name";
};
#include <iostream>
#include <string>
#include "CTable.h"
using namespace std;
CTable::CTable() {
s_name = NAME;
cout << "bezp: " << s_name << endl;
piTable = new int[SIZE];
i_size = SIZE;
}
///
CTable::CTable(CTable& pcOther) {
s_name = pcOther.s_name + "_copy";
piTable = new int[pcOther.i_size];
i_size = pcOther.i_size;
for (int i = 0; i < pcOther.i_size; i++) {
piTable[i] = pcOther.piTable[i];
}
cout << "kopiuj: " << s_name << endl;
}
CTable::~CTable() {
delete[] piTable;
cout << "usuwam " << s_name << endl;
}
////
bool CTable::bSetNewSize(int iTableLen) {
if (iTableLen <= 0) {
return false;
}
int* pi_newTable = new int[iTableLen];
memcpy(pi_newTable, piTable, iTableLen);
delete this->piTable;
this->i_size = iTableLen;
this->piTable = pi_newTable;
return true;
}
///
void CTable::vSetValueAt(int iOffset, int iNewVal) {
if (iOffset >= this->i_size) {
return;
}
piTable[iOffset] = iNewVal;
}
void CTable::vPrint() {
for (int i = 0; i < i_size; i++) {
cout << piTable[i] << " ";
}
cout << endl;
}
CTable CTable::operator+(const CTable& pcNewTable) {
CTable result;
int greater_len = i_size < pcNewTable.i_size;
int smaller_len = i_size > pcNewTable.i_size;
int* greater_table = i_size > pcNewTable.i_size ? piTable : pcNewTable.piTable;
int* smaller_table = i_size <= pcNewTable.i_size ? piTable : pcNewTable.piTable;
result.i_size = greater_len;
result.piTable = new int[greater_len];
memcpy(result.piTable, greater_table, greater_len * sizeof(int));
for (int i = 0; i < smaller_len; i++) {
result.piTable[i] += smaller_table[i];
}
return result;
}
What should I correct?
Try to define
CTable(const CTable& pcOther)
{
.......
}

Segmentation fault after everything executes-dynamic memory allocation: c++

I am fairly new to dynamic memory allocation and am having trouble. I'm thinking the problem is within my allocation function but I could be wrong. Here is the MyString.cpp file.
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "MyString.h"
using namespace std;
MyString::MyString()
{
m_size = 0;
buffer_allocate(0);
}
MyString::MyString(const char * str)
{
m_size = strlen(str);
buffer_allocate(m_size);
for(int i = 0; i < m_size; i++)
{
m_buffer[i] = str[i];
}
}
MyString::MyString(const MyString & other_myStr)
{
m_size = other_myStr.size();
buffer_allocate(other_myStr.size());
for(int i = 0; i < other_myStr.size(); i++)
{
m_buffer[i] = other_myStr.c_str()[i];
}
}
void MyString::buffer_deallocate()
{
delete[] m_buffer;
m_size = 0;
}
void MyString::buffer_allocate(size_t size)
{
try
{
m_buffer = new char[size];
}
catch(bad_alloc& ex)
{
delete[] m_buffer;
}
}
MyString::~MyString()
{
buffer_deallocate();
}
size_t MyString::size() const
{
return m_size;
}
size_t MyString::length() const
{
return m_size - 1;
}
const char* MyString::c_str() const
{
char * arr = (char*) malloc(m_size + 1);
int i;
for(i = 0; i < m_size; i++)
{
arr[i] = m_buffer[i];
}
arr[i] = '\0';
return arr;
}
bool MyString::operator== (const MyString & other_myStr) const
{
for(int i = 0; (i < m_size) && (i < other_myStr.size()); i++)
{
if(m_buffer[i] != other_myStr.c_str()[i])
{
return false;
}
}
if(m_size != other_myStr.size())
{
return false;
}
return true;
}
MyString & MyString::operator= (const MyString & other_myStr)
{
buffer_deallocate();
buffer_allocate(other_myStr.size());
for(int i = 0; i < other_myStr.size(); i++)
{
m_buffer[i] = other_myStr.c_str()[i];
}
return *this;
}
MyString MyString::operator+ (const MyString & other_myStr) const
{
int length = this->size() + other_myStr.size();
char * temp = (char*)malloc(length);
int j = 0;
for(int i = 0; i < length; i++)
{
if(i < this->size())
{
temp[i] = m_buffer[i];
}
else
{
temp[i] = other_myStr.c_str()[j];
j++;
}
}
MyString rhs = MyString(temp);
return rhs;
}
char & MyString::operator[] (size_t index)
{
return m_buffer[index];
}
const char & MyString::operator[] (size_t index) const
{
return m_buffer[index];
}
std::ostream & operator<<(std::ostream & os, const MyString & myStr)
{
for(int i = 0; i < myStr.size(); i++)
{
os << myStr[i];
}
os << endl;
}
Like I said, the segmentation fault is happening after the entire program is being executed so my guess is that there is some memory leak issue. I appreciate the help in advance.
And here is the main function:
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include "MyString.h"
using namespace std;
int main(void)
{
MyString dft;
if(dft.size() == 0)
{
cout << "Successful Default c-tor" << endl;
}
MyString param("Successful Parameter c-tor");
MyString copy(dft);
cout << param;
MyString ms_size_length("Size and length test:");
cout << ms_size_length;
cout << "Size of MyString: " << ms_size_length.size() << endl;
cout << "Length of MyString: " << ms_size_length.length() << endl;
MyString ms_toCstring("C-String equivalent successfully obtained!");
cout << ms_toCstring.c_str() << endl;
MyString ms_same1("The same"), ms_same2("The same");
if (ms_same1==ms_same2)
{
cout << "Same success" << endl;
}
MyString ms_different("The same (NOT)");
if (!(ms_same1==ms_different))
{
cout << "Different success" << endl;
}
MyString ms_assign("Before assignment");
ms_assign = MyString("After performing assignment");
MyString ms_append1("The first part");
MyString ms_append2(" and the second");
MyString ms_concat = ms_append1 + ms_append2;
cout << ms_concat;
MyString ms_access("Access successful (NOT)");
ms_access[17] = 0;
cout << ms_access;
}
One problem that I noticed is:
m_size = strlen(str);
buffer_allocate(m_size);
That allocates one less than the number of characters you need. As a consequence, you end up not copying the terminating null character to the object's m_buffer.
I suggest changing the constructor to:
MyString::MyString(const char * str)
{
m_size = strlen(str)+1;
buffer_allocate(m_size);
strcpy(m_buffer, str);
}
PS I did not look for other problems in your code. There may be more, or none.

What does it mean to multiply structure members in this c++ code

I have a question concerning this code from Thinking in c++ book , this is a tiny c style library for learning the process of memory allocation , what does it mean to write
int startBytes = s->next * s->size;
in this code , what does this multiplication mean ?
//: C04:CLib.h
// Header file for a C-like library
// An array-like entity created at runtime
typedef struct CStashTag {
int size;
// Size of each space
int quantity; // Number of storage spaces
int next;
// Next empty space
// Dynamically allocated array of bytes:
unsigned char* storage;
} CStash;
void initialize(CStash* s, int size);
void cleanup(CStash* s);
int add(CStash* s, const void* element);
void* fetch(CStash* s, int index);
int count(CStash* s);
void inflate(CStash* s, int increase);
///:~
//: C04:CLib.cpp {O}
// Implementation of example C-like library
// Declare structure and functions:
#include "CLib.h"
#include <iostream>
#include <cassert>
using namespace std;
/ Quantity of elements to add
// when increasing storage:
const int increment = 100;
void initialize(CStash* s, int sz) {
s->size = sz;
s->quantity = 0;
s->storage = 0;
s->next = 0;
}
int add(CStash* s, const void* element) {
if(s->next >= s->quantity) //Enough space left?
inflate(s, increment);
// Copy element into storage,
// starting at next empty space:
int startBytes = s->next * s->size;
unsigned char* e = (unsigned char*)element;
for(int i = 0; i < s->size; i++)
s->storage[startBytes + i] = e[i];
s->next++;
return(s->next - 1); // Index number
}
void* fetch(CStash* s, int index) {
// Check index boundaries:
assert(0 <= index);
if(index >= s->next)
return 0; // To indicate the end
// Produce pointer to desired element:
return &(s->storage[index * s->size]);
}
int count(CStash* s) {
return s->next; // Elements in CStash
}
void inflate(CStash* s, int increase) {
assert(increase > 0);
int newQuantity = s->quantity + increase;
int newBytes = newQuantity * s->size;
int oldBytes = s->quantity * s->size;
unsigned char* b = new unsigned char[newBytes];
for(int i = 0; i < oldBytes; i++)
b[i] = s->storage[i]; // Copy old to new
delete [](s->storage); // Old storage
s->storage = b; // Point to new memory
s->quantity = newQuantity;
}
void cleanup(CStash* s) {
if(s->storage != 0) {
cout << "freeing storage" << endl;
delete []s->storage;
}
} ///:~
//: C04:CLibTest.cpp
//{L} CLib
// Test the C-like library
#include "CLib.h"
#include <fstream>
#include <iostream>
#include <string>
#include <cassert>
using namespace std;
int main() {
// Define variables at the beginning
// of the block, as in C:
CStash intStash, stringStash;
int i;
char* cp;
ifstream in;
string line;
const int bufsize = 80;
// Now remember to initialize the variables:
initialize(&intStash, sizeof(int));
for(i = 0; i < 100; i++)
add(&intStash, &i);
for(i = 0; i < count(&intStash); i++)
cout << "fetch(&intStash, " << i << ") = "
<< *(int*)fetch(&intStash, i)
<< endl;
// Holds 80-character strings:
initialize(&stringStash, sizeof(char)*bufsize);
in.open("CLibTest.cpp");
assert(in);
while(getline(in, line))
add(&stringStash, line.c_str());
i = 0;
while((cp = (char*)fetch(&stringStash,i++))!=0)
cout << "fetch(&stringStash, " << i << ") = "
<< cp << endl;
cleanup(&intStash);
cleanup(&stringStash);
} ///:~
It looks like it's getting the next free location by multiplying the size of the object by the index number of the next available space. So if the next space is 10, and the object size is 10, it will start allocating at byte index 100.
It is a straight multiplication of the values of next and size, I'm going to guess it's calculating an offset somewhere. From looking at the code, size is set by the sz parameter of the initialize function.