
|
View Full Version : Crashing programs in C... ack
JPortal 03-02-2005, 05:28 PM Hmm...
My C program keeps crashing and behaving weird.
I have somewhat of an idea of what may be going on, but I'm not too sure...
I've been programming for about 4 years now, I'm 15. Most of my experience is in PHP, Java, and all the internet-related stuff like Javascript, CSS etc. I've been programming C for a few weeks so don't be too harsh :stickout:
Anyhoo, here's a little sample of my code. I have a string library that automatically deals with reallocating space for strings. This isn't the exact code but the idea is there:
void string_copy (char* dest, char* src)
{
// do we need to allocate space for dest?
if (dest == NULL || strlen(src) > strlen(dest))
{
// reallocate/allocate....
char* temp = do_allocate();
if (temp!=NULL)
{
dest = temp;
}
else
{
// handle errors
}
}
// copy
strcpy(dest, src);
}
// .........
main (int argc, char** argv)
{
char* str;
strcpy(str, "test string");
printf("%s", str);
}
Now, string_copy works fine. If I do a printf(dest) at the end of string_copy, it works as expected. But the printf in main prints (null).
I know that returning references to local variables is a bad idea. But what about the above? I use malloc, so shouldn't I be able to return that? Am I missing something? Or is the problem that I'm assigning dest = temp, which is a local variable??
:confused:
JPortal 03-02-2005, 05:36 PM OK, I fixed my problem, but I still want an explanation....
I fixed it by returning char* from string_copy. It returns dest. Now I call it like this:
string = string_copy(string, "test");
That works. But why didn't it work before?
Uptime 03-02-2005, 11:33 PM Originally posted by JPortal
But why didn't it work before?
C requires a bit more attention to memory management than you may be used to with PHP and Java.
There were at least 2 problems with the code as you posted it.
char* str;
strcpy(str, "test string");
The "str" variable needs to have memory allocated before using with strcpy.
if (dest == NULL || strlen(src) > strlen(dest))
{
// reallocate/allocate....
char* temp = do_allocate();
if (temp!=NULL)
{
dest = temp;
}
else
{
// handle errors
}
}
There is a memory leak in the case where strlen(src) > strlen(dest) ...
JPortal 03-03-2005, 12:02 PM In the real code, I check if dest is NULL. If it is, then I allocate char(*)*strlen(src) bytes of memory to it. It it's not NULL, I check the length of src with dest. Which is kind of pointless, and leads me to this questions:
I have memory management functions that keep a running tally of allocated and freed space, but they're a little flawed; I just have memory_allocate, which works like malloc but saves the # of bytes allocated. Then memory_free takes three arguments: a pointer to the address, like free(), the size of the variable type (sizeof(char*)) and the number of array elements.
However, they're reporting memory leaks when their are none:
// test....
char* src = "test, test, etc";
char* desc = memory_allocate(sizeof(char*)*strlen(src));
strcpy(desc, src);
// do some stuff with desc, now reset the string
strcpy(desc, "abc");
// now free desc
memory_free(desc, sizeof(char*), strlen(desc));
See where my problems are coming from? memory_free (and me) only knows that desc has been allocated 3*sizeof(char*) bytes!
Is there any way to find out how many bytes/indexes of space has been allocated to a certain variable?
krumms 03-03-2005, 12:22 PM Originally posted by JPortal
char* src = "test, test, etc";
char* desc = memory_allocate(sizeof(char*)*strlen(src));
strcpy(desc, src);
if memory_allocate is calling malloc, you should be passing:
sizeof (char) * (strlen (src)+1)
So:
1. You should be allocating an array of characters, not an array of character pointers.
2. You need to add +1 for the null string terminator. Without it, strcpy will be writing to the Mysterious Beyond and you'll likely screw up memory in other parts of your program.
// now free desc
memory_free(desc, sizeof(char*), strlen(desc));
why on earth do you need to specify the string length here, or even the fact that you're deallocating characters?
See where my problems are coming from? memory_free (and me) only knows that desc has been allocated 3*sizeof(char*) bytes!
Is there any way to find out how many bytes/indexes of space has been allocated to a certain variable?
If you're using standard C, you should have two functions called malloc & free. Use malloc to allocate memory in the same way you're using memory_allocate. Use free (desc) to free the memory allocated to desc - the C runtime will know how big it is.
You could always save yourself the hassle of all this and just use strdup ().
krumms 03-03-2005, 12:24 PM Just fyi, there are better memory management schemes out there too. Look for apr_pool for example, which approaches the topic in a different way (less places where memory needs to be deallocated, so less places you need to be mindful of memory deallocation)
JPortal 03-03-2005, 12:38 PM why on earth do you need to specify the string length here, or even the fact that you're deallocating characters?
If you're using standard C, you should have two functions called malloc & free. Use malloc to allocate memory in the same way you're using memory_allocate. Use free (desc) to free the memory allocated to desc - the C runtime will know how big it is.
Right, but I want to know how big it is so I can detect memory leaks and also do checks every once in a while of how much memory is being used.
giraffedata 03-05-2005, 07:06 PM I think you don't understand just how primitive C is.
I think this because of statements like "Is there any way to find out how many bytes/indexes of space has been allocated to a certain variable?" You can't dynamically allocate space to a variable in C. The variable 'desc' in your program has 4 bytes allocated to it by the compiler. That's because it is a char * variable -- a pointer. The compiler represents a pointer with an address, which is probably 4 bytes on your machine.
Your memory_allocate() doesn't allocate memory to a variable. It just allocates memory and returns to you the address of that memory. So that you can use that address later, you assign that address to your pointer variable 'src'. The compiler has no concept of what is at that address or even that it's a valid memory address. That concept exists only in the code author's mind.
Why does it show a leak? The allocate allocates 76 bytes of memory (length of the string "test, test, etc" (19) times size of desc (4)). The free declares that it is freeing 12 bytes of memory (length of the string "abc" (3) times size of desc (4)). 76-12 means your accounting system reports a loss of 64 bytes. That's all there is to it.
I think the key thing is to realize that 'desc' and 'src' are _not_ strings and do not have the values "test, test, etc." or "abc". 'desc' is a pointer to a character. Its value is a memory address. The string is all in your mind because you've adopted the common C programming convention of representing a string with a piece of memory that contains the ASCII encodings of the characters of the string, one after another, followed by a NUL character and of identifying that string with a C variable that points to the first character in it.
|