Thread: Scope of memory allocation

  1. #1
    Registered User Xzyx987X's Avatar
    Join Date
    Sep 2003
    Posts
    107

    Scope of memory allocation

    I am writing a function to convert a number of any base up to 16 to a string. Here's what I have so far:

    Code:
    char * IntToString(int number, int base)
    {
    
    	int     i = 0;
    	char *  charArray;
    	int     digits;
    
    	// Base 16 is the maximum I decided to allow, but even "as is" this function could support higher numbers
    	if(base < 2 || base > 16)
    		return (char *) 0;
    
    	//Determine the memory required to hold the string
    	while(number)
    	{
    
    		number /= base;
    		i++;
    
    	}
    
    	//Save i as the total digits the number will take
    	digits = i;
    	
    	//Allocate memory for the string
    	if(!(charArray = (char *) malloc(i + 1)))
    		return (char *) 0;
    
    	//Put each digit of the number in it's own array position
    	for(i; i >= 0; i--)
    	{
    
    		charArray[i] = number % base;		
    		number /= base;
    
    		if(!(number))
    			break;
    
    	}
    
    	//Now convert the digits to their correct ASCII values
    	for(i = 0; i <= digits; i++)
    	{
    
    		if(charArray[i] < 10)
    			charArray[i] += 48;
    		else
    			charArray[i] += 55;
    
    	}
    
    	//Terminate the string
    	charArray[digits + 1] = '\0';
    
    	return charArray;
    
    }
    The only problem is (well let's not say only since I haven't finished testing the rest of the code...) that when I use malloc within a function then the memory gets freed once the function exits, or at least that's what I think is happening. In case you are wondering, yes I'm aware of the consequences of not following this up with a call to free() later on if this wasn't the case . Anyway, I could put the code to determine the how many digits a number takes in a seporate function and allocate the memory within the scope it will be used in, but I think this method makes for neater code so I'd like to get it working if possible. All I need is a function that allocates memory in a way so that it will not get deallocated unless I explicitly say it should be. Anyone know of one? I'm writing this code for a windows based program if it makes a difference. Also, if you happen to notice any other bugs in this feel free to point them out .


    Mod edit: changed php tags to code tags

  2. #2
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    I see a lot potential problems here but I'll point out a few things to you first.

    First and foremost:

    Code:
    charArray[digits + 1] = ';
    Probably meant new line character per your comment '\n'.

    When you are finding out how many digits there are you are modifying the original number then later you try to use it and it is 0. Just use a temporary variable for determing number of digits so you don't modify the original. You can use the logarithm function to help you get number of digits easily if you want.

    This should push you in the right direction, just step through it in the debugger and you'll spot some errors there. Let me know if you get stuck again.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  3. #3
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    Your corruption problem is due to the fact that you destroy number when finding the number of digits and then try to use it again to build your string. Then you have a multitude of off-by-one errors in your indexing, but you can find those when you save a copy of number to work with after finding digits.

    I like the avatar. "Love and peace! Love and peace!"
    My best code is written with the delete key.

  4. #4
    Registered User Xzyx987X's Avatar
    Join Date
    Sep 2003
    Posts
    107
    Originally posted by MrWizard
    I see a lot potential problems here but I'll point out a few things to you first.

    First and foremost:

    Code:
    charArray[digits + 1] = ';
    Probably meant new line character per your comment '\n'.

    Well actually I meant \0 but that was in my original code. PHP formatting must've done something to it.

    Originally posted by MrWizard
    When you are finding out how many digits there are you are modifying the original number then later you try to use it and it is 0. Just use a temporary variable for determing number of digits so you don't modify the original. You can use the logarithm function to help you get number of digits easily if you want.
    Yea, can't believe I missed that. I was just assuming I had messed up the memory handling somehow so I wasn't looking for that kind of thing that carefully

    Originally posted by MrWizard
    This should push you in the right direction, just step through it in the debugger and you'll spot some errors there. Let me know if you get stuck again.
    Well for once thing, if the scope of the memory allocation wasn't an issue then why does using free() at the address of the memory result in a memory damage error in Visual C++?

  5. #5
    Registered User Xzyx987X's Avatar
    Join Date
    Sep 2003
    Posts
    107
    Originally posted by Prelude
    Your corruption problem is due to the fact that you destroy number when finding the number of digits and then try to use it again to build your string. Then you have a multitude of off-by-one errors in your indexing, but you can find those when you save a copy of number to work with after finding digits.

    I like the avatar. "Love and peace! Love and peace!"
    Yea, off-by-one errors are often my downfall. Oh and I'm glad to see there are other anime fans on this board .

  6. #6
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    '\n', doh , yea I meant \0 too, hah.

    Using free on the memory you allocated shouldn't give you any problems unlessed you messed up somewhere along the way. Watch out for invalid indexing as Prelude was mentioning. Just get your algorithm working first then worry about freeing the memory, that's not the most important thing at the moment.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  7. #7
    Registered User Xzyx987X's Avatar
    Join Date
    Sep 2003
    Posts
    107
    Ok here is fully working code (not gurenteed though ), now with support for negative numbers. Anyone is free to use it who finds it useful (although for all I know someone has probobly allready written better code to do the same thing.) Thanks for the help. Any additional improvements or suggestions for my code would be appreciated if you can find something that looks like it could use improving.

    Code:
    char * IntToString(int number, int base)
    {
    
    	int     i = 0;
    	BOOL    sign = 0;
    	char *  charArray;
    	int     digits;
    	int     tempNum;
    
    	// Base 16 is the maximum I decided to allow, but even "as is" this function could support higher numbers
    	if(base < 2 || base > 16)
    		return (char *) 0;
    
    	// Determine if the number is negative
    
    	if (number < 0)
    	{
    
    		sign = 1;
    		number = -number;
    
    	}
    	// Determine the memory required to hold the string
    
    	tempNum = number;
    
    	while(tempNum)
    	{
    
    		tempNum /= base;
    		i++;
    
    	}
    
    	// Save i as the total digits the number will take to store
    	digits = i;
    	
    	// Allocate memory for the string
    	if(!(charArray = (char *) malloc(digits + 1 + sign)))
    		return (char *) 0;
    
    	//Insert a dash if the number is negative
    	if(sign)
    		charArray[0] = 45;
    
    	// Put each digit of the number in it's own array position
    	for(i -= !(sign); i >= sign; i--)
    	{
    
    		charArray[i] = number % base;		
    		number /= base;
    
    		if(!(number))
    			break;
    
    	}
    
    	// Now convert the digits to their correct ASCII values
    	for(i = sign; i <= digits; i++)
    	{
    
    		if(charArray[i] < 10)
    			charArray[i] += 48;
    		else
    			charArray[i] += 55;
    
    	}
    
    	// Terminate the string
    	charArray[digits + sign] = '\0';
    
    	return charArray;
    
    }

  8. #8
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Your function doesn't convert 0 too well. For example:
    p = IntToString(0, 10);
    gives an empty string (one byte containing the \0). I would expect it to contain a 0 character.

    You shouldn't be using magic numbers in your code, like you do here:
    charArray[0] = 45;
    Instead, you character constants, like so:
    charArray[0] = '-';
    It's more portable, and much easier to read.

    Your use of malloc() gives me two concerns:
    First: http://faq.cprogramming.com/cgi-bin/...&id=1043284351
    Second: you're relying on the caller to free the memory. A better way, imho, would be to accept a char pointer and length indicator as function parameters, and write to those instead. That way the caller can decide where they want the string written to, and they are fully aware if it's dynamic memory or not.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Understanding Memory Allocation
    By Ragsdale85 in forum C Programming
    Replies: 7
    Last Post: 10-31-2005, 08:36 AM
  2. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM
  3. Nested loop frustration
    By caroundw5h in forum C Programming
    Replies: 14
    Last Post: 03-15-2004, 09:45 PM
  4. Varibale scope and memory allocation
    By Guang Yan Wang in forum C Programming
    Replies: 2
    Last Post: 02-25-2004, 09:16 AM
  5. scope of memory allocation
    By doubleanti in forum C++ Programming
    Replies: 3
    Last Post: 02-16-2002, 10:22 PM