Memory Validator reports a problem: Accessing C++ object functions with a pointer to a deleted object.
It is pointing to prefDir = preferredPath;

in Loader.h Public: is defined:

std::vector<std::string> preferredPaths;

in Loader.ccp

CDirLoader::GetFileExtHandle(not related params)


std::string prefDir;
for(size_t i=0;i<preferredPaths.size();++i)
	{
		const std::string& preferredPath=preferredPaths[i];

		if (!preferredPath.empty()) 
				prefDir = preferredPath;  // HERE IT REPORTS PROBLEM

Recommended Answers

All 15 Replies

can you put the error message here please?

Just this one:
Error: Accessing C++ object functions with a pointer to a deleted object.
And it highlights this line prefDir = preferredPath;

I think the real problem is here:
const std::string& preferredPath=preferredPaths;
you cannot convert char to string& type

I think the real problem is here:
const std::string& preferredPath=preferredPaths;
you cannot convert char to string& type

Could you post please some suggestions how to solve that ?

What happens if you try this

CDirLoader::GetFileExtHandle(not related params)
{
    std::string prefDir;
    for(size_t i=0;i<preferredPaths.size();++i)
    {
        if (!preferredPaths[i].empty()) 
            prefDir = preferredPaths[i];
            //...
    }
}

What happens if you try this

CDirLoader::GetFileExtHandle(not related params)
{
    std::string prefDir;
    for(size_t i=0;i<preferredPaths.size();++i)
    {
        if (!preferredPaths[i].empty()) 
            prefDir = preferredPaths[i];
            //...
    }
}

Actually I will get the same error:
Error: Accessing C++ object functions with a pointer to a deleted object.
And it points to your line 7:
prefDir = preferredPaths;

Is preferredPaths a member of your CDirLoader class? How is the vector filled? Also there is no return type for the function. Did you omit it or is there not one?

Is preferredPaths a member of your CDirLoader class? How is the vector filled? Also there is no return type for the function. Did you omit it or is there not one?

I am starting to think that this is false positive.

>>Is preferredPaths a member of your CDirLoader class?
Yes.

class CDirLoader  
{
   protected:
      std::vector<std::string> preferredPaths;
}

>>How is the vector filled?

void CDirLoader::AddPreferredPath(const std::string& pp)
{
	std::string preferredPath=pp;
	LoCase(preferredPath);
	if (preferredPaths.empty())
	{
		preferredPaths.push_back(preferredPath);
		return;
	}

	//check if preferredPaths already contains preferredPath
	for(size_t i=0;i<preferredPaths.size();++i)
		if (preferredPaths[i]==preferredPath)
			return;

	//if not, so add it
	preferredPaths.push_back(preferredPath);
}

>>Also there is no return type for the function.

fileHandle CDirLoader::GetFileExtHandle(const std::string &_fname, char extensionType, int dirTypes)
{
	std::string fname(_fname);
	LoCase(fname);

        // This function is really long
        // Three pages of code

	return Handle();
}

the thing is should never ever trust vector or any type(extept linked list) containers for keeping pointers or reference to kontainer elements, becouse when vector needs more memory it realocates memory somewhere else and the pointers becomes invalid I assume this is the problem...

Actually a vector is guaranteed to have there data in one block of memory.

from http://www.cplusplus.com/reference/stl/vector/

Vector containers are implemented as dynamic arrays; Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements.

a linked list actually can have its data all over the memory because they only point to other nodes.

from http://www.cplusplus.com/reference/stl/list/

List containers are implemented as doubly-linked lists; Doubly linked lists can store each of the elements they contain in different and unrelated storage locations. The ordering is kept by the association to each element of a link to the element preceding it and a link to the element following it.

Does the code work properly and you are only getting an error from Memory Validator? If that is the case it might be a false positive. Do you modify the vector in any way before you try to get the string from it?

Ok, best way is to show you the whole Loader.cpp and Loader.h

They are attached. Please download it and take a look.
They are protected by password so just send send me a massage and I will send you a password to my complete directory loader program.

yes you are absolutely right, but there is word BUT.. when a vector allocates memory it'll preallocate it for the first time 64 elements space of a particular type after first insertion(it might vary for different systems), try to craete first vector of any type and then push one element, and check memory with the fucntion capacity():

#include <iostream>
#include <vector>

using namespace std;
int main(){
	vector<int> coll;
	for (int i=5;i<50;i++){
	coll.push_back(i);
	cout<<"number of elements is able to put under current block:"<<coll.capacity()<<endl;
	cout<<"number of elements::"<<coll.size()<<endl;
	}
	system("pause");
	return 0;
}

When you push 28th element to the vector it'll allocate space for 42, it can be ofcource adjecent memory block but it can be somewhere else, so for this reason it can not be trusted as long as you use insertion functions. It always can be done in safe way..for more refference read The C++ STL library - Josuttis.

The data in a vector is held in a dynamic array. As such the memory has to be contiguous. The address of the array can change when the array is re-sized but the elements are guaranteed to be contiguous.

Nathan memory is contious and it will always be for vectors, deques. You can use simple pointers to iterate vectors or c libraries with it, but you can not trust pointers to elements to be valid after you use an insertion function such as puch_back().Particulalry, if vector capacity is exceeded vector reallocates memory but memory stays continious, but address of the new block(the address of the first element will might be different).
check again this example and notice the address of the first element gets invalidated:

#include <iostream>
#include <vector>

using namespace std;
int main(){
	vector<int> coll;
	coll.push_back(1);
	
	int* p=&coll[0];	//the address of the first element
	cout<<"the value referenced of the pointer *p\t"<<(*p)<<endl;
	coll.push_back(2);
	cout<<"the value referenced of the pointer *p\t"<<(*p)<<endl;
	
	for (int i=3;i<50;i++){ //realloaction is specific to an implementation 

		coll.push_back(i);
		cout<<"number of elements is able to put under current block:\t"<<coll.capacity()<<endl;
		cout<<"number of elements:\t"<<coll.size()<<endl;
		cout<<"the value referenced of the pointer *p\t"<<(*p)<<endl;
	}
	system("pause");
	return 0;
}

Nathan memory is contious and it will always be for vectors, deques.

For vectors, yes. For deques, there's no requirement that memory be contiguous.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.