Here's what I'm trying to do:

create an empty/NULL char * in one place, pass it to a function who will populate it (and tell me the size), and then use the char * elsewhere. However, when I get out of the function..

Here's the function that expects the char * and attempts to populate it:

bool FileUtilities::loadFullFileBinary( const string &filename, char * fileContents, long & sizeOfContents )
 
{
 
FILE *file = fopen(filename.c_str(), "rb");
 
if ( !file )
 
returnfalse;
 
 
 
 
 
fseek(file, 0, SEEK_END);
 
sizeOfContents = ftell(file);
 
cout<<"SIZE:"<<sizeOfContents<<endl;
 
rewind(file);
 
fileContents = newchar[sizeOfContents];
 
if ( fileContents )
 
{
 
if ( !fread(fileContents, sizeOfContents, 1, file) == 1 )
 
{
 
//puts(buffer);
 
delete [] fileContents;
 
sizeOfContents=0;
 
returnfalse;
 
}
 
}
 
fclose(file);
 
returntrue;
 
}

Here's the code (assume in main()) trying to use it.

char * me=NULL;
 
long size;
 
bool status = FileUtilities::loadFullFileBinary("test.txt", me, size );
 
if ( !status )
 
throw DHException(*this, "Couldn't read file" );
 
else
 
{
 
multiLog.writeLog( "SIZE WAS '%ld'", size );
 
if ( me != NULL )
 
{
 
cout<<"TEST:"<<me[0]<<endl;
 
cout<<"TEST:"<<me[1]<<endl;
 
}
 
else
 
cout<<"WAS NULL"<<endl;
 
 
 
}

I am finding that the char * is populated inside the function (loadFullFileBinary) but when I attempt to look at it after the function has returned, it is null... What am I doing wrong? (You can ignore the DHException and multiLog bit, they are not related to the problem...)

Recommended Answers

All 11 Replies

OK, I've tried to simplify the example. Same problem happens here:

#include <iostream.h>
void test( char * fillMe )
{
		fillMe = new char[10];
		memset( fillMe, '\0', 10 );
		strcpy( fillMe, "TESTING" );
}
int main()
{
		char * tester=NULL;
		test( tester );
		if ( tester == NULL )
		{
				cout<< "tester is null"<<endl;
		}
		else
				cout<<tester[0]<<endl;
 
}

Result:
./Test
tester is null

I was able to get it to work, however is this the right way?

#include <iostream.h>
void test( char ** fillMe)
{
		*fillMe = new char[10];
		memset( *fillMe, '\0', 10 );
		strcpy( *fillMe, "TESTING" );
}
int main()
{
		char * tester=NULL;
		test( &tester );
		if ( tester == NULL )
		{
				cout<< "tester is null"<<endl;
		}
		else
				cout<<tester<<endl;
		if ( tester !=NULL )
				delete [] tester;
 
 
}

Result:
./Test
TESTING

fillMe is a copy of the pointer, so you're allocating memory to a copy, then the copy is destroyed, thus destroying your only reference to the memory. This is affectionately called a memory leak. The solution in C is to pass a pointer to the pointer so that you can get to the original object:

#include <cstring>
#include <iostream>

using namespace std;

void test( char ** fillMe )
{
  *fillMe = new char[10];
  strcpy( *fillMe, "TESTING" );
}

int main()
{
  char * tester = NULL;

  test( &tester );

  if ( tester == NULL )
  {
    cout<< "tester is null"<<endl;
  }
  else
    cout<< tester <<endl;
}

Notice that I included <cstring>, which is required for memset and strcpy, and I also removed memset because there's no point in using it since you'll just use strcpy right after.

The C++ version using references is even easier:

#include <cstring>
#include <iostream>

using namespace std;

void test( char *& fillMe )
{
  fillMe = new char[10];
  strcpy( fillMe, "TESTING" );
}

int main()
{
  char * tester = NULL;

  test( tester );

  if ( tester == NULL )
  {
    cout<< "tester is null"<<endl;
  }
  else
    cout<< tester <<endl;
}

If I might direct you here, you'll probably have an easier time with pointers.

I didn't seem to need to include cstring, must be somehow automatically included based on my compiler setup.

In the second version that I posted, I do a delete [] on tester, doesn't that take care of any memory leaks?

>must be somehow automatically included based on my compiler setup.
That's nice. Now forget about it. Your code is not portable if you rely on such things.

>doesn't that take care of any memory leaks?
Yes, but only because you correctly assigned the memory to tester by using a pointer to a pointer. If you had not made that change, no amount of deleting would stop the memory leak. Once again, I urge you to read the tutorial so that you know what the problem was and why the fix fixed it.

I'm feeling quite confuzzled...

When you pass a pointer to a function make sure to allocate the memory before passing to the function.

In your program u were not allocating memory before passing on to the function. The memory was allocated within the function. Which was in the local scope of the function itself. The memory was not there in the scope from where the function was called. Hence you were not able to see it in the main.

Else you need to send a pointer to pointer in order to get access to the original object.

Hope this helps to come out from the state of confuzzled...

>Hope this helps to come out from the state of confuzzled...
If you had bothered to read the entire thread before posting, you would have found that I gave a more correct explanation and solution, except with useful code and a link to a useful tutorial. So the only unique part of your post that I can see is bad advice:

When you pass a pointer to a function make sure to allocate the memory before passing to the function.

Please note that my advice was not for you but for winbatch who wrote this word 'confuzzled' after you message in the same thread.

My intention was not to make any advice as you may be more knowledgeable than me.

I've made my comment after seeing all the messages in the thread. The way it appeared - seems winbatch was the last one to post. I just explained my views about the same.

>Please note that my advice was not for you but for winbatch
I'm well aware of that. However, you gave an inaccurate explanation where I had already given an accurate explanation. Repeating an answer given previously is generally not helpful. Doing so incorrectly is even less helpful.

>who wrote this word 'confuzzled' after you message in the same thread.
You misinterpreted his post as meaning he didn't understand. That's fine, but I don't like it when someone pops up and attempts to give the same explanation that I did, except gets it wrong. That's confusing to the OP, and I usually end up having to clean up the mess.

>I just explained my views about the same.
You may understand the issue, but you explained it very poorly. It's not a scope issue, and the solution of passing a pointer to a pointer is doubly confusing when you explain the problem as if it is a scope issue.

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.