Double Pointer Allocation, and Validity Testing Errors?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Devun_06
Posts: 15
Joined: Sat Jun 17, 2006 7:01 pm

Double Pointer Allocation, and Validity Testing Errors?

Post by Devun_06 »

I have a header declaring a double pointer, char **file.
But, my double pointer is not responding appropriately to the validity test I run on it. The error occurs as so:

Code: Select all

int max2 = 18;
char **file;
file=malloc(max2 * sizeof(char *));

int i;
for&#40;i=0; i< max2; i++&#41;file&#91;i&#93;=malloc&#40;1&#41;;

char *just_for_example;//assume equal to "NOTHING.EXE\0"

file&#91;0&#93;=realloc&#40;file&#91;0&#93;, strlen&#40;just_for_example&#41;+1&#41;; //or free&#40;file&#91;0&#93;&#41;; file&#91;0&#93;=malloc&#40;strlen&#40;just_for_example&#41;+1&#41;;

if&#40;sizeof&#40;*file&#91;0&#93;&#41; != strlen&#40;just_for_example&#41;&#41;&#123;/*display error*/&#125;
The problem is that it ALWAYS returns the display error comment code, the program returns it is not the proper size each and every time it is called. In the ACTUAL CODE below, the error returns:
"DIR FILE, RESTRICTED FROM MEMORY. HEAP CLOSED. :1"
a unique value that indicates ONLY the size verification is inaccurate, and EXACTLY where the problem is located. (search feature will locate problem area)

But, I'm not sure my testing is correct. I've tested this method of validity checking on SINGLE pointers, but not double, as I'm trying, and it fails, and improper checking just leads to memory leaks. I assume the checking is the same since in the process, I'm checking the variable without first referring to the pointer that points to it. I'm completely stuck, and after weeks of mindlessly frustrating myself over the issue, I've just decided to work amongst others who might be able to note what I'm overlooking.

The code for it all is below, modulated and all, some features were being tested, and are therefore commented out. Also, because this function was in development, numerous changes have left older, obsolete methods commented out as well.

To gather how these pieces are used, FIRST, the initiation is used, SECOND, the browse function is used.

Header

Code: Select all

#ifndef Dir_Bank_H
#define Dir_Bank_H


















Initiate Allocation Process.

Code: Select all

	return 1;
&#125;




















Fill/Refill Allocated Variables

Code: Select all

return 1;
&#125;
Last edited by Devun_06 on Fri Jan 01, 2010 1:46 am, edited 3 times in total.
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

This is the error:

Code: Select all

if&#40;sizeof&#40;*file&#91;0&#93;&#41; != strlen&#40;just_for_example&#41;&#41;&#123;/*display error*/&#125;
file[0] is the pointer to "NOTHING.EXE\0". File si char **, so file[0] is a char *, so *file[0] is char, so its size will always be 1. You need to use this:

Code: Select all

if&#40;strlen&#40;file&#91;0&#93;&#41; != strlen&#40;just_for_example&#41;&#41;&#123;/*display error*/&#125;
Remember, use sizeof only for explicity declar arrays, like:

Code: Select all

char array&#91;20&#93;;

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
Devun_06
Posts: 15
Joined: Sat Jun 17, 2006 7:01 pm

Post by Devun_06 »

Thanks, I'm reviewing now. I'm going to try to make sense of it first, then test it. Shouldn't be too hard. Again, thank you.

Done. BRILLIANT! SIMPLY BRILLIANT. Makes complete sense, I can't believe I overlooked that. Really, I can't. Thanks!!!

I de-referenced the pointer to beyond what was needed, the identifier of an array will always point to the FIRST location, for anyone else who might need to know what happened here.

all chars (or characters) are 1 byte in size(example - sizeof('a')=1), and the FIRST location of the char *pointer, was the FIRST character. Because of pointer arithmetic, extracting the value of pointer is the letter one, extracting the value of pointer+1 is value 2, etc.

sizeof() returns ONLY the size in accordance to bytes. not any other form of computer measurement.

To conclude:
I got caught up in slinging the verification method everywhere with so many instances of allocation to work with, that I didn't notice that concern for weeks and almost screwed things up. Weeks of changing my code left and right elsewhere thinking it was everything else till I added informative returns. The confusion caught up with me, once again, thanks for helping me "ab5000".
Devun_06
Posts: 15
Joined: Sat Jun 17, 2006 7:01 pm

Post by Devun_06 »

That instance is not the problem(it's one of them), it just proved that even though I parsed through all the methods available for detecting size inaccurate values, the one I found to work of them all was horribly wrong. When I tested it, I first tried:
Ptr ==strlen()+1
Ptr ==strlen()+0
*Ptr ==strlen()+1
*Ptr ==strlen()+0

the test method was SHOT from the beginning without me first noticing. It happened because like I said before, I figured I was testing incorrectly, so I went through all cases till one worked. The test was destined to fail as it was developed on the following lines of code.


folder->bank_dir->dir = static [255]
fld_to_me_read = "ms0:/MUSIC/\0";

Code: Select all

sprintf&#40;folder->bank_dir->dir,"%s",fld_to_be_read&#41;;
		
		char * caught;
		caught=strrchr&#40;folder->bank_dir->dir,'/'&#41;;

		if &#40;caught != NULL&#41;
		&#123;
			folder->bank_dir->dis_dir=realloc&#40;&#40;folder->bank_dir->max<=0 ? NULL&#58;folder->bank_dir->dis_dir&#41;, strlen&#40;caught&#41;+1&#41;;
			if&#40;sizeof&#40;*folder->bank_dir->dis_dir&#41;==strlen&#40;caught&#41;&#41;//ptr & +1 &#58;failed; ptr & +0 &#58;failed; *ptr & +1 &#58;failed; *ptr & +0 &#58; successful;
			&#123;
				sprintf&#40;folder->bank_dir->dis_dir,"%s",caught&#41;;
			&#125;
			else
			//don't touch it, leave it how it was, the size and everything is still the same as it was before
			&#123;
				Set_Window_Notice&#40;folder,"DIR DISPLAY, OUT OF MEMORY. HEAP CLOSED. &#58;10"&#41;;
				Deallocate_Directory_Object&#40;folder&#41;;
				return 0;
			&#125;
		&#125;
The accident occured when I used strrchr, I hadn't realized the LAST character was the '/' I was searching for. BUT, that threw off even the proper case scenerio. Unfortunately that was what I meant by I had tested the method on a single pointer only, but thanks to the HORRIBLE testing environment, the entire thing got corrupted and *ptr ==strlen() *WORKED*(I was willing to accept anything at that moment). I had only done this to avoid the error message, as I knew those cases should have worked.

Can someone attempt to tell me what has screwed this all up, as I still obtain the same error case as I originally stated. I'm still grateful to the first assistance, but it was something else... something majorly wrong with this code. Something is killing these pointers.

I've reviewed the initiation process once again, and it doesn't seem to have any algorithm issues.

What's confusing is that the FUNCTION WORKS without the tests there, but that's dangerous, much too dangerous.

I tested the outputs of the data being verified for success. The method for doing so was:

Code: Select all

/*//TEST
			unsigned int num&#91;4&#93;;
			num&#91;0&#93; = sizeof&#40;folder->bank_dir->c->file&#91;counter&#93;&#41;;
			num&#91;1&#93; = strlen&#40;folder->bank_dir->c->file&#91;counter&#93;&#41;;
			num&#91;2&#93; = sizeof&#40;fldrt->d_name&#41;;
			num&#91;3&#93; = strlen&#40;fldrt->d_name&#41;;
			char research1&#91;255&#93;;
			char research2&#91;255&#93;;
			sprintf&#40;research1,"%s  byte size&#58;%d; string size&#58;%d;",folder->bank_dir->c->file&#91;counter&#93;,	num&#91;0&#93;,num&#91;1&#93;&#41;;
			sprintf&#40;research2,"%s  byte size&#58;%d; string size&#58;%d;",						fldrt->d_name,	num&#91;2&#93;,num&#91;3&#93;&#41;;
			print&#40;0,0,research1,rgb&#40;255,0,0&#41;&#41;;print&#40;0,10,research2,rgb&#40;255,0,0&#41;&#41;;flipScreen&#40;&#41;;while&#40;1&#41;&#123;&#125;;*/
The method " ptr==strlen() " is the CORRECT method, but it fails, yet, the program works when I don't check, what's wrong with this case? Even worse, why did the test instance fail, is a question I can live assuming it didn't capture the fact that it still had 1, ONE character in the return string as strrchr should've still grabbed the character being searched for. But, the proper method failed there as well.
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Code: Select all

The method " ptr==strlen&#40;&#41; " is the CORRECT method, but it fails
No. You cannot check the size of an allocated memory region like this.

There are only two cases:
a) The allocation succeeded, hence the pointer points to exactly the amount of allocated ram
b) the allocation failed, hence the pointer is null and no memory was allocated

So, all you have to do is check if the (re)alloc returned NULL or not.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Devun_06
Posts: 15
Joined: Sat Jun 17, 2006 7:01 pm

Post by Devun_06 »

Why is it that the size of the allocated space cannot be tested?
Isn't realloc supposed to return the value of the pointer untouched in some cases? I want to embed the realloc process in another that will check for null, and in the case of null, return the pointer to the original like so:

Code: Select all

void *vi_realloc &#40;void *pointer, unsigned long long size&#41;
&#123;
	void *mem = realloc &#40;pointer, size&#41;;

return &#40;mem == NULL ? pointer &#58; mem&#41;;
&#125;
but it checks for null too, but since the allocation size specified is that size specifically, why would it fail? I can't wrap my brain around the fact, but I trust your every word.

I specifically checked for NULL first to prevent crashes, and attempting to pull the size of a NULL block reference. The quote you noted is an abbreviation of the actual process.

I used sizeof(ptr) == strlen()
if that quoted statement was taken literally I apologize for that, I was only pointing out "how" I referenced the pointer and what I compared it to.
for instance, in that same post, I displayed the instance of the test as the following:

Code: Select all

if&#40;sizeof&#40;*folder->bank_dir->dis_dir&#41;==strlen&#40;caught&#41;&#41;//ptr & +1 &#58;failed; ptr & +0 &#58;failed; *ptr & +1 &#58;failed; *ptr & +0 &#58; successful; 
I can easily omit the code, but why is it that the size cannot be checked to verify the pointer is allocated correctly if realloc successfully acquired the memory space?
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

sizeof(*folder->bank_dir->dis_dir)

calculates the size of the thing pointed to by dis_dir, which is a char, therefore it always returns 1. sizeof knows nothing about malloc.

Jim
Devun_06
Posts: 15
Joined: Sat Jun 17, 2006 7:01 pm

Post by Devun_06 »

Thanks Jim.

No, the question has been completely distorted now, and to prevent further confusion this is a summery.

*Summery*
I tried testing pointers as the first helpful reply had insisted, but I was unsure because of the failed response, and had decided to figure out what the problem was, and blamed it on the variable being a double pointer. The test case failed because of a horrible testing environment, the variable manipulation insisted strrchr() be used, and the test "sizeof(ptr)==strlen()" failed even though it logically made sense. Because of this, I tested ALL instances just to find what I thought was the right method so I did the following.

if(sizeof(Ptr) ==strlen()+1)
if(sizeof(Ptr) ==strlen()+0)
if(sizeof(*Ptr) ==strlen()+1)
if(sizeof(*Ptr) ==strlen()+0)

but, this is AFTER the allocation of the ptr. All of them failed the test but one, so I took the success of the test, and blindly applied it to the real issue. The real issue CONTINUED to fail, even using the same successful method in the test. This confused me beyond belief, so I requested help.

I stopped trusting my methods as I knew the code worked when I had no checks applied. So, after doubting my own knowledge, ab5000 put me back on track telling me that my test case "if(sizeof(*Ptr) == strlen())"
may have worked for bypassing the check in that case, but was not what I was intending to do. So, like he stated, I went back and used the same method as had failed before and used "if(sizeof(Ptr) == strlen())" and it still gave me the error "DIR FILE, RESTRICTED FROM MEMORY. HEAP CLOSED. :1".

Since I knew that ab5000 had agreed with my original belief, I was able to corner the problem even further. I tested the first loop instance and yes, it returned sizeof(file)==strlen() *PASSES*, the string pointed to was "Cool\0" the size of the string, and allocation size was correct, they had to be if realloc did not return NULL, because I specifically told it how many blocks to gather.

Both sizeof(ptr) and strlen() returned 4 so they passed, but I keep getting that same error message, so somewhere in there, it messes up. When ANY allocation fails to successfully allocate, or even gets NULL returned, the error line is printed to the screen, and ALL other allocation is freed appropriately in reverse order. But, NULL is tested first, so if the value returned was NULL, it would print "DIR FILE, RESTRICTED FROM MEMORY. HEAP CLOSED. :2" Notice the error return has "2" at the end. My situation says that the return is NOT NULL because I nested the statements in

Code: Select all

file&#91;i&#93;=realloc&#40;file&#91;i&#93;,strlen&#40;story&#41;+1&#41;;
if &#40;file&#91;i&#93; != NULL&#41;
&#123;
     if&#40;sizeof&#40;file&#91;i&#93;&#41; != strlen&#40;story&#41;&#41;
     &#123;
          print &#40;"DIR FILE, RESTRICTED FROM MEMORY. HEAP CLOSED. &#58;1"&#41;;
     &#125;
&#125;
else
&#123;
print &#40;"DIR FILE, RESTRICTED FROM MEMORY. HEAP CLOSED. &#58;2"&#41;; 
&#125;
I'm trying to give cases without making anyone read those large code blocks, but like the code I JUST posted above this sentence, "IT IS NOT, NOT, NOT! THE ACTUAL CODE" ignore syntax errors, and short abbreviations. The question has been pinpointed by Raphael, that maybe the size cannot be compared in all cases, but... in this case, it is "NOT" NULL, because the error string has the 1 on the end instead of a 2.

This means something else is wrong, and dying to try to figure it out, either the loop stretches out of bounds and reads a pointer that is not valid, a pointer is not properly allocated, or like Raphael has said, the variable cannot be checked using this method. I hope this isn't the case, but I seriously think the pseudo code abbreviations misinformed Raphael of the actual code's problem, or I'd like to know that if sizeof won't return the proper value in all cases, why is that, because without knowing why, I can't prevent this from happening again.

I've drawn this out on paper, aluminum foil, and finally a whiteboard for larger representation, and have not yet come to see a problem in the overall algorithm that starts, or connects the initiation to the browse function, nor have I found an error in the browse function. The only actual code representations of the error are in those large 3 code sections of the original post. I can remove the * that de-references the pointer that is being check RIGHT THERE WHERE THE ERROR CONDITION ACTIVATES, but that won't help, as I've already done that and tested it working as the sizeof does return the correct value to match the string length used to calculate the allocation size. I don't care about the rest of the function, just that ONE part. You can ignore the header too, it's just there so that you can see why things were allocated as they were if you feel as I do, that the problem could very well be ANYTHING that is so minor it's overlooked.


I tested the sizeof(file[]) data and strlen() with

Code: Select all

folder->bank_dir->c->file&#91;counter&#93; = realloc&#40;  folder->bank_dir->c->file&#91;counter&#93;, strlen&#40; fldrt->d_name &#41;+1&#41;;//method 1
//free&#40;folder->bank_dir->c->file&#91;counter&#93;&#41;;folder->bank_dir->c->file&#91;counter&#93;=malloc&#40;strlen&#40; fldrt->d_name &#41;+1&#41;;//method 2

if&#40;folder->bank_dir->c->file&#91;counter&#93; != DEAD&#41;
&#123;
   if&#40; sizeof&#40;folder->bank_dir->c->file&#91;counter&#93;&#41; != strlen&#40;fldrt->d_name&#41; &#41;
   &#123;
      Set_Window_Notice&#40;folder,"DIR FILE, RESTRICTED FROM MEMORY. HEAP CLOSED. &#58;1"&#41;;Terminate_Directory_Bank&#40;folder&#41;;   return 0;//ptr & +1 &#58;failed; ptr & +0 &#58;failed;
   &#125;
         /*//TEST
         unsigned int num&#91;4&#93;;
         num&#91;0&#93; = sizeof&#40;folder->bank_dir->c->file&#91;counter&#93;&#41;;
         num&#91;1&#93; = strlen&#40;folder->bank_dir->c->file&#91;counter&#93;&#41;;
         num&#91;2&#93; = sizeof&#40;fldrt->d_name&#41;;
         num&#91;3&#93; = strlen&#40;fldrt->d_name&#41;;
         char research1&#91;255&#93;;
         char research2&#91;255&#93;;
         sprintf&#40;research1,"%s  byte size&#58;%d; string size&#58;%d;",folder->bank_dir->c->file&#91;counter&#93;,   num&#91;0&#93;,num&#91;1&#93;&#41;;
         sprintf&#40;research2,"%s  byte size&#58;%d; string size&#58;%d;",                  fldrt->d_name,   num&#91;2&#93;,num&#91;3&#93;&#41;;
         print&#40;0,0,research1,rgb&#40;255,0,0&#41;&#41;;print&#40;0,10,research2,rgb&#40;255,0,0&#41;&#41;;flipScreen&#40;&#41;;while&#40;1&#41;&#123;&#125;;*/
THESE ARE THE SAME CODES AS ABOVE BUT SLIMMMED DOWN, AND ALTERED ACCORDING TO THE ADVICE FOUND HERE, WITH EXCEPTIONS. *IN THE BROWSE FUNCTION* I LEFT THE CHAR * CAUGHT INSTANCE AS sizeof(*->dir) == strlen() because it works for bypassing the fail response, and it's so minute, and even necessary that I don't mind it being broke for this moment, because if I correct it, the function wouldn't even reach the error I'm here to conquer.

Initiate Allocation Process.

Code: Select all

&#125;




















Fill/Refill Allocated Variables

Code: Select all

return 1;
&#125;
Last edited by Devun_06 on Fri Jan 01, 2010 1:48 am, edited 1 time in total.
coyotebean
Posts: 18
Joined: Sat Dec 05, 2009 1:02 am

Post by coyotebean »

file is of type char*, sizeof(file) equals to sizeof(char*). The result is always 4 in this case. I don't know if you can get the size of the memory allocated from the pointer.
ab5000
Posts: 74
Joined: Tue May 06, 2008 2:37 am

Post by ab5000 »

You can't get the size of a malloc'd memory region with standard libc functions. But you can take a look at the mallocr.c for the newlib: http://sourceware.org/cgi-bin/cvsweb.cg ... vsroot=src

You can see this:
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if allocated | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk, in bytes |P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User data starts here... .
. .
. (malloc_usable_space() bytes) .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Just a linked list. Scroll down, you can find this:

Code: Select all

/* Get size, ignoring use bits */

#define chunksize&#40;p&#41;          &#40;&#40;p&#41;->size & ~&#40;SIZE_BITS&#41;&#41;
so you can just use this in your code (search a bit in the code to resolve all the defines...):

Code: Select all

/* Get allocated memory size */
#define mallocsize&#40;p&#41; &#40;*&#40;&#40;&#40;size_t *&#41; &#40;p&#41;&#41; - 1&#41; & 0xFFFFFFFC&#41;
Note that this isn't standard, and if newlib malloc changes this will not work. You should keep track of the allocated memory size.

Code: Select all

%&#58;include<stdio.h>
int _&#40;int __,int ___,int ____,int _____&#41;
<%for&#40;;____<___;_____=_____*__,____++&#41;;
return _____;%>main&#40;&#41;<%printf
&#40;"%d\n",_&#40;2,5,0,1&#41;&#41;;%>
Devun_06
Posts: 15
Joined: Sat Jun 17, 2006 7:01 pm

Post by Devun_06 »

Thanks Everyone, I'm assuming since I can't, but the "Cool\0" == strlen() case both equaled four, it must've been just another horrible test situation.

I don't know for sure, but I find it easier to believe sizeof() returned 4 for the test case, not because there were four letters, which would've made no sense anyways, seeing how it had to be 5 to hold NULL. But, because the size of the pointer is always set to 32 bits, which divided by 8, returns 4.(I fell asleep and jumped out of bed with this idea.)

Thanks alot everyone, I'm just going to remove that overly defensive code, finish the product, and then incorporate another method for verifying the success, possibly freeing then mallocing and reviewing errno flag values. If that doesn't work, I'll just stick with checking for NULL.

Those are beautiful macros, and it'd be easy to change there functions to fit slightly new changes to the newlib. But, I'll run it else where for things like loading, I refuse to put it into this function and have to begin re-evaluating this large beast again to find the error.

THANKS ALOT EVERYONE! *RESOLVED*
Post Reply