Pointer in a pair in C++ - c++

I need to return an array and it's size:
pair<int*, int> load(string path,int * memory){
ifstream handle;
int container;
int size = 0;
if(!handle){
QMessageBox::warning(0, QString(""), "file cannot be loaded");
return make_pair(NULL,-1);
}
handle.open(path.c_str());
while(!handle.eof()){
handle >> container;
size++;
}
size--;
if(!size){
QMessageBox::warning(0, QString(""), "file is empty");
return make_pair(NULL,-1);
}
memory = new int[size];
handle.clear();
handle.seekg(0, ios::beg);
for(int i = 0; i < size; i++){
handle >> memory[i];
}
handle.close();
return make_pair(memory, size);
}
The error output is:
/usr/include/c++/4.6/bits/stl_pair.h:109: error: invalid conversion
from 'int' to 'int*' [-fpermissive]
How do I do it?

Since NULL is probably defined as:
#define NULL 0
the expression make_pair(NULL,-1) becomes make_pair(0, -1), so it creates pair<int, int>. You can for example use nullptr if available or (int*)NULL otherwise.

Related

Heap corruption when using delete

I have a MultiString class that has some methods in it.
I am strugling with deleting my array of strings in the destructor, I get heap corruption.
Here is my class (some methods are cut)
class MultiString {
public:
//constructor destructor
MultiString(int);
~MultiString();
//methods
void Setat(int nindex, const char* str);
//attributes
char** buf;//pointer to vector
int str_nmb;//strings number
};
Constructor code:
MultiString::MultiString(int number)
{
str_nmb = number;
buf = new char* [number];
for (int i = 0; i < number; i++) buf[i] = NULL;
}
Setat code (used to set strings in array):
void MultiString::Setat(int nindex, const char* str)
{
if (nindex<0 || nindex>str_nmb || str == NULL) {
std::cout << "gg";
return;
}
char* tmp = new char[strlen(str)+1];
if (tmp == NULL) return;
if (buf[nindex] != NULL) delete buf[nindex]; //here delete works fine
buf[nindex] = tmp;
strcpy_s(buf[nindex], strlen(buf[nindex]), str);
std::cout << buf[nindex]<< std::endl;
}
Destructor code:
MultiString::~MultiString()
{
for (int i = 0; i < str_nmb; i++)
delete buf[i]; // heap corruption here
delete buf;
}
And my main():
int main()
{
MultiString* ms = new MultiString(3);
ms->etat(0, "qwerty");
ms->Setat(1, "asdfgh");
ms->Setat(2, "zxcvbn");
delete ms;
return 0;
}
char* tmp = new char[strlen(str)+1];
// ...
buf[nindex] = tmp;
strcpy_s(buf[nindex], strlen(buf[nindex]), str);
buf[nindex] points to the freshly allocated, but uninitialized memory area. Calling strlen on that is undefined behavior and likely what corrupts your heap. You probably want to call strlen(str) instead.
Apart from that you're making a few other mistakes:
Rule of 0/3/5 broken.
delete where delete[] would be necessary
Wrong bounds check (nindex>str_nmb)
What about Multistring(-5) ?
if (tmp == NULL) return; ... no, you shouldn't mute errors. Throw an exception or something.
Also .. why strcpy_s ? Use std::strncpy ... that's at least guaranteed to be available! Make sure the copied C string is null terminated!

Getting error while trying to copy STL Set into Vector

I am trying to initialize vector by already preset Set but getting error
vector<string> findRepeatedDnaSequences(string s) {
int size = s.length();
set<string>container;
unordered_map<string,int>hmap;
for(int i=0;i<size;i++){
string first=s.substr(i,10);
if(hmap.find(first)!=hmap.end()){
// if((i-hmap[first])>=10)
container.insert(first);
}else hmap[first] = i;
}
// ERROR IN THIS LINE
return vector<string>res(container.begin(), container.end());
}
anagrams.cpp:21:26: error: expected '(' for function-style cast or type construction return vector<string>res((container.begin(), container.end()));

memory error in c++ binary search algo "*** Error in `./Drivers': free(): invalid next size (normal): 0x000000000166c2d0 ***"

So my code worked for my lab on c++ memory errors, but although it worked I keep getting the "* Error in `./Drivers': free(): invalid next size (normal): 0x000000000166c2d0 *" error, and along with that comes the back trace and the memory map. So I was just wondering why such problem is occuring.
Here is my code:
int binarySearch(const Array<NYCTaxiDriver>& aSortedList,
unsigned int aKey,
int aBegin,
int aEnd
)
{
if(aEnd >= aBegin){
int avg = (aBegin+aEnd)/2;
if(aSortedList[avg].getMedallionNumber() == aKey){
return avg;
}
if(aSortedList[avg].getMedallionNumber()>aKey){
return binarySearch(aSortedList,aKey, aBegin, avg-1);
}
return binarySearch(aSortedList,aKey, avg+1, aEnd);
}
return -1;
}
void printTheMatchingDrivers(const Array<unsigned int>& aManhattanMedallions,const Array<NYCTaxiDriver>& aMatchedDrivers)
{
int size = aMatchedDrivers.getSize();
for(int i=0;i<aManhattanMedallions.getSize()-1;i++){
int resultPos = binarySearch(aMatchedDrivers,aManhattanMedallions[i],0,size);
if(resultPos != -1){
cout<<"Match "<<1<< ":"<<"\n"<<aMatchedDrivers[resultPos].getMedallionNumber()<<": "<<aMatchedDrivers[resultPos].getLastName()<<", "<<aMatchedDrivers[resultPos].getFirstName()<<endl;
}
}
}
int main(){
Array<unsigned int> manhattanMedallions;
Array<NYCTaxiDriver> matchedDrivers;// already sorted
printTheMatchingDrivers(manhattanMedallions, matchedDrivers);
return 0;
}
The issue seems to be in the container class Array.

Pointer Arithmetic with a pointer to a class array

I'm having issues with this code for a bag ADT. I'm using a a pointer array made of a separate class that stores a string and an int.
ArrayBag::ArrayBag(int length){
list = new ReceiptArray [length];
size = length;
n= 0;
}
int ArrayBag::getCurrentSize(){return n;};
bool ArrayBag::isEmpty() {
if (!(n==0)){
return 1;
cout << "has items"<< endl;
}
else{
cout << "empty" << endl;
return 0;
}
}
bool ArrayBag::add(string item){
if (!(n==size)){
(*list+n.item) = item;
(*list+n.itemnum) = n+1;
it is the pointer arithmetic lines above that are proving difficult
n++;
return 1;
}
else{
cout << "bag full" << endl;
return 0;}
}
bool ArrayBag::remove(string item){
for(int k=0;k<n;k++){
Here too
if ((*list+k.item) == item){
(*list+k.item) = (*list+n.item);
n--;
return true;
}
}
return false;
}
void ArrayBag::clear(){n=0;}
int ArrayBag::getFrequencyOf(string item){
int frequency = 0;
for(int k=0;k<n;k++){
if(*list+k.item == item){
++frequency;}
}
return frequency;
}
bool ArrayBag::contains(string item){
for(int k=0;k<n;k++){
if(*list+k.item == item){
return 1;
}
}
return 0;
}
The errors
error: request for member ‘item’ in ‘((ArrayBag*)this)->ArrayBag::n’, which is of non-class type ‘int’
(*list+n.item) = item;
I'm confused on why this is happening. I thought you could index the pointer array this way. It happens anywhere where I try to add the current size of the array to properly index the array and access the arrays member variables.
Any advice is welcome
You have: (*list+n.item) where list is a pointer to a ReceiptArray (you should probably rename the class from ReceiptArray to Receipt but that's not your issue.)
You have two issues:
1) An order of operation issue. First *list is evaluated which returns an object of type ReceiptArray. But you need to increment your pointer before you dereference it.
2) Next you try to add n.item to this object. But n is an int and doesn't have an item member. Hence the error.
You want: (*(list+n)).item = item;
Or: (list+n)->item = item
Or simply: list[n] = item;

2D Array Memory Allocation (malloc) Returns NULL

I am trying to compile a 64-bit CPP code using GCC, however multidimensional (i.e. 2D) array memory allocation returns NULL once I increase the element size from 46,000 to 46,500. My virtual memory is set to 96GB, and hardware is running 64-bit OS using 32GB Ram. The code works fine as long as MAX_VERTICES does not exceed 46000.
Following is what I am trying to dynamically allocate:
struct ShortestPath {
real32 totalWeight;
// NOTE: ShortestPath is a list of pointers; does not make copies
// (i.e. side-effects) the pointers point to memory allocated
// in the DijkstraSPTree array in the vehicle_searching module
List<DirectedEdge *> *edgeList;
};
#define MAX_VERTICES 46500
global_variable ShortestPath spAllPairs[MAX_VERTICES][MAX_VERTICES];
Allocate Memory on the Heap to replace
spAllPairs[MAX_VERTICES][MAX_VERTICES]
with the following code
global_variable ShortestPath **spAllPairs;
global_variable ShortestPath *arr_data;
ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source,
int32 dest)
{
free(spAllPairs); // Function is called multiple times so I clear memory
free(arr_data); // before reallocation given values pointed by pointers
free(spTreesArray); // are used in other files in my project after run.
inline allocate_mem(ShortestPath*** arr, ShortestPath** arr_data, int n, int m);
allocate_mem(&spAllPairs, &arr_data, MAX_VERTICES, MAX_VERTICES);
for (unsigned int k = 0 ; k < MAX_VERTICES ; k++) {
if (spAllPairs[k] == NULL) {
while (k >= 1) {
free(spAllPairs[k]);
--k;
}
free(spAllPairs[0]);
free(spAllPairs);
fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n");
exit(1);
}
}
spTreesArray = (DijkstraSPTree *)malloc(MAX_VERTICES * sizeof(DijkstraSPTree));
for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) {
pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo],
vertexTo);
}
return &spAllPairs[source][dest];
}
void pathTo(DijkstraSPTree *spTree, ShortestPath *shortestPath, int32 dest)
{
List<DirectedEdge *>::traverseList(freeDirectedEdge, shortestPath->edgeList);
List<DirectedEdge *>::emptyList(&shortestPath->edgeList);
shortestPath->totalWeight = spTree->distTo[dest];
}
int allocate_mem(ShortestPath ***arr, ShortestPath **arr_data, int n, int m)
{
*arr = (ShortestPath **)malloc(n * sizeof(ShortestPath*));
*arr_data = (ShortestPath *)malloc(n * m * sizeof(ShortestPath));
for (int i = 0; i < n; i++)
(*arr)[i] = *arr_data + i * m;
return 0; //free point
}
The function allocate_mem is inconsistent with the code used in getShortestPath to free the structures. If arr_data is not used elsewhere, you should remove this global variable and allocate an indirect array this way:
ShortestPath **allocate_mem(int n, int m) {
ShortestPath **arr = (ShortestPath **)calloc(n, sizeof(*arr));
if (arr != NULL) {
for (int i = 0; i < n; i++) {
arr[i] = (ShortestPath *)calloc(m, sizeof(ShortestPath));
if (arr[i] == NULL)
break;
}
}
return arr;
}
Notes:
it would be safer to store NULL into the global pointers after you free the memory they point to.
it would be more consistent for allocate_mem to check if it could allocate all the array elements and free whatever was allocated if not, instead of trying to clean up in the caller function.
Here is a more consistent version and the calling code:
ShortestPath **allocate_mem(int n, int m) {
ShortestPath **arr = (ShortestPath **)calloc(n, sizeof(*arr));
if (arr != NULL) {
for (int i = 0; i < n; i++) {
arr[i] = (ShortestPath *)calloc(m, sizeof(ShortestPath));
if (arr[i] == NULL) {
for (j = i; j-- > 0;) {
free(arr[j]);
}
free(arr);
return NULL;
}
}
}
return arr;
}
ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source,
int32 dest)
{
// Function is called multiple times so I clear memory
// before reallocation given values pointed by pointers
// are used in other files in my project after run.
free(spAllPairs);
spAllPairs = NULL;
free(arr_data);
arr_data = NULL;
free(spTreesArray);
spTreesArray = NULL;
spAllPairs = allocate_mem(MAX_VERTICES, MAX_VERTICES);
if (spAllPairs == NULL) {
fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n");
exit(1);
}
spTreesArray = (DijkstraSPTree *)malloc(MAX_VERTICES * sizeof(DijkstraSPTree));
if (spTreesArray == NULL) {
fprintf(stderr, "Failed to allocate space for DijkstraSPTree!\n");
exit(1);
}
for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) {
pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo],
vertexTo);
}
return &spAllPairs[source][dest];
}
EDIT as M.M commented, you should use the new and delete operators in C++ instead of malloc() and free(). (or in addition to malloc, but why bother with malloc anyway):
ShortestPath **allocate_mem(int n, int m) {
ShortestPath **arr = new ShortestPath *[n];
if (arr != NULL) {
for (int i = 0; i < n; i++) {
arr[i] = new ShortestPath[m];
if (arr[i] == NULL) {
for (j = i; j-- > 0;) {
delete[] arr[j];
}
delete[] arr;
return NULL;
}
}
}
return arr;
}
ShortestPath *getShortestPath(EdgeWeightedDigraph *digraph, int32 source,
int32 dest)
{
// Function is called multiple times so I clear memory
// before reallocation given values pointed by pointers
// are used in other files in my project after run.
delete[] spAllPairs;
spAllPairs = NULL;
delete[] spTreesArray;
spTreesArray = NULL;
spAllPairs = allocate_mem(MAX_VERTICES, MAX_VERTICES);
if (spAllPairs == NULL) {
fprintf(stderr, "Failed to allocate space for Shortest Path Pairs!\n");
exit(1);
}
spTreesArray = new DijkstraSPTree *[MAX_VERTICES];
if (spTreesArray == NULL) {
fprintf(stderr, "Failed to allocate space for DijkstraSPTree!\n");
exit(1);
}
for (int32 vertexTo = 0; vertexTo < digraph->vertices; ++vertexTo) {
pathTo(&spTreesArray[source], &spAllPairs[source][vertexTo],
vertexTo);
}
return &spAllPairs[source][dest];
}