473,473 Members | 2,126 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

dynamic memory problem(i think)

Hi all,

i have this struct for a binary tree node

typedef struct treenode
{
char *word;
struct treenode *right;
struct treenode *left;
}TreeNode;

and to the element *word, i dynamically allocate memory for it as below
(and also for the TreeNode too)
addNode(TreeNode*,char*);

char *token, buf[BUF_MAX], *memWord;
TreeNode *root;

/*do memory allocation check */

while((fgets(buf,BUF_MAX,filePtr)) != NULL)
{
/* do buffer handling here */
token = strtok(buf,"\n");
while (token != NULL)
{
/* is the following right ? */
memWord = malloc(sizeof(char) * strlen(token);
strcpy(memWord,token);

addNode(root,memWord);
token = strtok(NULL, "\n");
}
}
the code above reads a line from a file and then tokenizes the line
read into tokens and then allocates memory in the same length of the
token, then copies the token into memWord and passes to a function to
add it to the BST pointed by root.

My question and problem is that , when i delete a node from the list
and free the memory for both the word inside the node and the node
itself, i get no memory leaks or whatsoever (because according to
valgrind i have more free's then allocations) and then print them out
(in-order), well, i get weird characters and mumble jumble for insted
of words. But if i dont free the word inside the node (and get some
memory leaks) then print them out it actually works, i.e the nodes that
deleted are gone and there is no weird characters and all. So anyway
here is the code that i use to delete a node (recursive)

delete(char *w, TreeNode T)
{
TreeNode tmpNode;
if (T == NULL)
return T;
if (strcmp(w, T->word) < 0 )
T->left = delete(w,T->left);
else
if (strcmp(w, T->word) > 0)
T->right = delete(w,T->right);
else
{
if(T->left && T->right)
{
tmpNode = findMin(T->right);
T->word = tmpNode -> word;
T->right = delete(w,T->right);
}
else
{
tmpNode = T;
if (T->left == NULL)
T= T->right;
else if (T->right == NULL)
T= T->left;

free(tmpNode->word);
free(tmpNode);
}

}

return T;
}

Nov 15 '05 #1
14 1569
placid wrote:
Hi all,

i have this struct for a binary tree node

typedef struct treenode
{
char *word;
struct treenode *right;
struct treenode *left;
}TreeNode;

and to the element *word, i dynamically allocate memory for it as below
(and also for the TreeNode too)
Please post *real* code. Copy and paste!
addNode(TreeNode*,char*);

char *token, buf[BUF_MAX], *memWord;
TreeNode *root;

/*do memory allocation check */

while((fgets(buf,BUF_MAX,filePtr)) != NULL)
{
/* do buffer handling here */
token = strtok(buf,"\n");
while (token != NULL)
{
/* is the following right ? */
memWord = malloc(sizeof(char) * strlen(token);
Here's your problem.
First of all, sizeof(char) == 1 by definition, so it's superfluous.
More important, however, is that you've allocated one char too few; you
haven't left room for the null char that terminates the string.

Make the above line:
memWord = malloc(strlen(token) + 1));

[BTW - I know you haven't posted *real* code as you're missing a closing
paren above.]

You also need to check that malloc() did not return NULL.
strcpy(memWord,token);


Now, since you haven't allocated enough memory, your call to strcpy()
invokes undefined behavior. You were fortunate that nasal demons(tm) did
not ensue!

[snip]

HTH,
--ag
--
Artie Gold -- Austin, Texas
http://goldsays.blogspot.com (new post 8/5)
http://www.cafepress.com/goldsays
"If you have nothing to hide, you're not trying!"
Nov 15 '05 #2

Artie Gold wrote:
placid wrote:
Hi all,

i have this struct for a binary tree node

typedef struct treenode
{
char *word;
struct treenode *right;
struct treenode *left;
}TreeNode;

and to the element *word, i dynamically allocate memory for it as below
(and also for the TreeNode too)
Please post *real* code. Copy and paste!


yeah, see for some reason i always have two copies of code(really bad
idea) one on my laptop and one a UNIX server, so i had to type it out
all again so i was just trying to save some time. Sorry man

addNode(TreeNode*,char*);

char *token, buf[BUF_MAX], *memWord;
TreeNode *root;

/*do memory allocation check */

while((fgets(buf,BUF_MAX,filePtr)) != NULL)
{
/* do buffer handling here */
token = strtok(buf,"\n");
while (token != NULL)
{
/* is the following right ? */
memWord = malloc(sizeof(char) * strlen(token);


Here's your problem.
First of all, sizeof(char) == 1 by definition, so it's superfluous.
More important, however, is that you've allocated one char too few; you
haven't left room for the null char that terminates the string.


so then strlen does not include the null character in the lenght count

Make the above line:
memWord = malloc(strlen(token) + 1));

[BTW - I know you haven't posted *real* code as you're missing a closing
paren above.]

You also need to check that malloc() did not return NULL.
sacrificed for code readablity !
strcpy(memWord,token);
Now, since you haven't allocated enough memory, your call to strcpy()
invokes undefined behavior. You were fortunate that nasal demons(tm) did
not ensue!


thats why i get "weird characters and mumble jumble"

[snip]

HTH,
--ag
your a life saver man

greatly appreciated

--
Artie Gold -- Austin, Texas
http://goldsays.blogspot.com (new post 8/5)
http://www.cafepress.com/goldsays
"If you have nothing to hide, you're not trying!"


Nov 15 '05 #3
Artie Gold wrote:
placid wrote:
Hi all,

i have this struct for a binary tree node

typedef struct treenode
{
char *word;
struct treenode *right;
struct treenode *left;
}TreeNode;

and to the element *word, i dynamically allocate memory for it as below
(and also for the TreeNode too)

Please post *real* code. Copy and paste!

addNode(TreeNode*,char*);

char *token, buf[BUF_MAX], *memWord;
TreeNode *root;

/*do memory allocation check */

while((fgets(buf,BUF_MAX,filePtr)) != NULL)
{
/* do buffer handling here */
token = strtok(buf,"\n");
while (token != NULL)
{
/* is the following right ? */
memWord = malloc(sizeof(char) * strlen(token);

Here's your problem.
First of all, sizeof(char) == 1 by definition, so it's superfluous.


However, using

memWord = malloc( (sizeof *memWord) * (strlen(token)+1) );

is a much better practice...
--
one's freedom stops where others' begin

Giannis Papadopoulos
http://dop.users.uth.gr/
University of Thessaly
Computer & Communications Engineering dept.
Nov 15 '05 #4
Artie Gold wrote:
placid wrote:
[snip]
Here's your problem.
First of all, sizeof(char) == 1 by definition, so it's superfluous.
More important, however, is that you've allocated one char too few; you
haven't left room for the null char that terminates the string.

Make the above line:
memWord = malloc(strlen(token) + 1));


I know FAQ 7.8 covers exactly the above point
but I also noticed in the errata section
(http://www.eskimo.com/~scs/C-faq/book/Errata.html) 1.1
that the sizeof(char) is *atleast* 8 bits.

So 'theoritically' speaking [probably 'practically' in some cases but
not in my experience] sizeof(char) is not really superfluous in the
situations..

-Anand
Nov 15 '05 #5
Anand wrote:
Artie Gold wrote:
placid wrote:

[snip]

Here's your problem.
First of all, sizeof(char) == 1 by definition, so it's superfluous.
More important, however, is that you've allocated one char too few;
you haven't left room for the null char that terminates the string.

Make the above line:
memWord = malloc(strlen(token) + 1));


I know FAQ 7.8 covers exactly the above point
but I also noticed in the errata section
(http://www.eskimo.com/~scs/C-faq/book/Errata.html) 1.1
that the sizeof(char) is *atleast* 8 bits.

So 'theoritically' speaking [probably 'practically' in some cases but
not in my experience] sizeof(char) is not really superfluous in the
situations..

-Anand

Sorry.. typed too fast.. upon going through the C99 std and also going
through news groups more thoroughly found the following article titled:
"Type sizes (Was:big-endian vs. little-endian...)"
http://groups.google.com/group/comp....81ff433d688fa6
-Anand
PS: Is there any way to point to another news group article through some
kind of link (apart from this looong google link)?
Nov 15 '05 #6
On 2005-09-05 06:30:31 -0400, Anand <An***@no-replies.com> said:
Artie Gold wrote:
placid wrote:

[snip]

Here's your problem.
First of all, sizeof(char) == 1 by definition, so it's superfluous.
More important, however, is that you've allocated one char too few; you
haven't left room for the null char that terminates the string.

Make the above line:
memWord = malloc(strlen(token) + 1));


I know FAQ 7.8 covers exactly the above point
but I also noticed in the errata section
(http://www.eskimo.com/~scs/C-faq/book/Errata.html) 1.1
that the sizeof(char) is *atleast* 8 bits.

So 'theoritically' speaking [probably 'practically' in some cases but
not in my experience] sizeof(char) is not really superfluous in the
situations..


Even when char is more than 8-bits, sizeof(char) is *always* 1. Char
could be 135 bits, and it would still be one byte in size, as that is
C's definition of "byte".
--
Clark S. Cox, III
cl*******@gmail.com

Nov 15 '05 #7
Anand wrote:
Artie Gold wrote:
placid wrote:
[snip]

Here's your problem.
First of all, sizeof(char) == 1 by definition, so it's superfluous.
More important, however, is that you've allocated one char too few;
you haven't left room for the null char that terminates the string.

Make the above line:
memWord = malloc(strlen(token) + 1));


I know FAQ 7.8 covers exactly the above point
but I also noticed in the errata section
(http://www.eskimo.com/~scs/C-faq/book/Errata.html) 1.1
that the sizeof(char) is *atleast* 8 bits.


No, sizeof(char) is always EXACTLY 1 on all conforming implementations.
CHAR_BIT (i.e. the number of bits in a char) *may* me more than 8, but
since all allocations, the result of strlen, the result of sizeof are
all working on the basis of the number of bytes (in C terms 1 char is
the size of 1 byte ALWAYS, even if 1 byte is 932754937 bits long).
So 'theoritically' speaking [probably 'practically' in some cases but
not in my experience] sizeof(char) is not really superfluous in the
situations..


sizeof(char) is, by definition, ALWAYS 1, but that is 1 C byte which
could be more than 8 bits.

IMHO it is misleading for the FAQ Errata to say, "sizeof(char) is at
least 8 bits". It should say, "The size of one char is at least 8 bits".

Also, note that there are conforming implementations where
sizeof(char)==sizeof(int) where both int and char are 16 bits.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 15 '05 #8
Giannis Papadopoulos wrote:
Artie Gold wrote:
placid wrote:
Hi all,

i have this struct for a binary tree node

typedef struct treenode
{
char *word;
struct treenode *right;
struct treenode *left;
}TreeNode;

and to the element *word, i dynamically allocate memory for it as below
(and also for the TreeNode too)

Please post *real* code. Copy and paste!

addNode(TreeNode*,char*);

char *token, buf[BUF_MAX], *memWord;
TreeNode *root;

/*do memory allocation check */

while((fgets(buf,BUF_MAX,filePtr)) != NULL)
{
/* do buffer handling here */
token = strtok(buf,"\n");
while (token != NULL)
{
/* is the following right ? */
memWord = malloc(sizeof(char) * strlen(token);

Here's your problem.
First of all, sizeof(char) == 1 by definition, so it's superfluous.


However, using

memWord = malloc( (sizeof *memWord) * (strlen(token)+1) );

is a much better practice...

In general, yes. In this case, however, the type is effectively
constrained by the use of strlen() anyway. (And in any case the parens
around the `sizeof' expression are superfluous.)

But I'm just nit-picking...

Cheers,
--ag
--
Artie Gold -- Austin, Texas
http://goldsays.blogspot.com (new post 8/5)
http://www.cafepress.com/goldsays
"If you have nothing to hide, you're not trying!"
Nov 15 '05 #9
placid <Bu****@gmail.com> wrote:
so then strlen does not include the null character in the lenght count


No.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 15 '05 #10
>
delete(char *w, TreeNode T)
{
TreeNode tmpNode;
if (T == NULL)
return T;
if (strcmp(w, T->word) < 0 )
T->left = delete(w,T->left);
else
if (strcmp(w, T->word) > 0)
T->right = delete(w,T->right);
else
{
if(T->left && T->right)
{
tmpNode = findMin(T->right);
T->word = tmpNode -> word;
T->right = delete(w,T->right);
}
else
{
tmpNode = T;
if (T->left == NULL)
T= T->right;
else if (T->right == NULL)
T= T->left;

free(tmpNode->word);
free(tmpNode);
}

}

return T;
}


aghh..

Ok.. i tried adding one to memWord = malloc(strlen(token) + 1)
that fixes the funny character problem, but like i said when i delete a
node from the tree and print it out im still getting data that is just
mumble jumble
i found out that when i call

free(tmpNode->word);

is the problem. when i run valgrind with that code commented (and print
the BST out it works) i get memory leaks (obviously) but the amount of
free's is equals to the amount of allocations. But when i use that line
of code then run valgrind (and print the BST out, i get mumble jumble)
i get more free's the allocations. and this is on a mandrake 10.1
official system (im beginning to think its an OS problem ).

Nov 15 '05 #11

Well,

I really feel you should have

TreeNode * deleta(char *w, TreeNode *T) {

}

i.e. the variable T should be a *pointer to* TreeNode instance, and
that applies to the 'left' and 'right' fields of TreeNode struct as
well.

HTH - Joakim
delete(char *w, TreeNode T)
{
TreeNode tmpNode;
if (T == NULL)
return T;
if (strcmp(w, T->word) < 0 )
T->left = delete(w,T->left);
else
if (strcmp(w, T->word) > 0)
T->right = delete(w,T->right);
else
{
if(T->left && T->right)
{
tmpNode = findMin(T->right);
T->word = tmpNode -> word;
T->right = delete(w,T->right);
}
else
{
tmpNode = T;
if (T->left == NULL)
T= T->right;
else if (T->right == NULL)
T= T->left;

free(tmpNode->word);
free(tmpNode);
}

}

return T;
}


--
Joakim Hove
hove AT ift uib no /
Tlf: +47 (55 5)8 27 13 / Stabburveien 18
Fax: +47 (55 5)8 94 40 / N-5231 Paradis
http://www.ift.uib.no/~hove/ / 55 91 28 18 / 92 68 57 04
Nov 15 '05 #12

Hello,
[....] and that applies to the 'left' and 'right' fields of
TreeNode struct as well [....]


and that was indeed the case, I remembered the definition of TreeNode
{} incorrectly. Sorry.

Joakim

--
Joakim Hove
hove AT ift uib no /
Tlf: +47 (55 5)8 27 13 / Stabburveien 18
Fax: +47 (55 5)8 94 40 / N-5231 Paradis
http://www.ift.uib.no/~hove/ / 55 91 28 18 / 92 68 57 04
Nov 15 '05 #13
placid wrote:

delete(char *w, TreeNode T)
{
TreeNode tmpNode;
if (T == NULL)
return T;
if (strcmp(w, T->word) < 0 )
T->left = delete(w,T->left);
else
if (strcmp(w, T->word) > 0)
T->right = delete(w,T->right);
else
{
if(T->left && T->right)
{
tmpNode = findMin(T->right);
T->word = tmpNode -> word;
assign the char * T->word to point to the word inside tmpNode->word but
its wrong for some reason

T->word is a pointer to a dynamically allocated char's, so the correct
way of doing it is ..

strcpy(T->word,tmpNode->word);

but why would that make a difference i dont know. (But it works).

T->right = delete(w,T->right);
}
else
{
tmpNode = T;
if (T->left == NULL)
T= T->right;
else if (T->right == NULL)
T= T->left;

free(tmpNode->word);
free(tmpNode);
}

}

return T;
}

Everybody thanks for the help

Nov 15 '05 #14
In article <11**********************@g14g2000cwa.googlegroups .com>
placid <Bu****@gmail.com> wrote [edited somewhat]:
typedef struct treenode {
char *word;
struct treenode *right;
struct treenode *left;
} TreeNode;

... when i delete a node from the list and free the memory for both
the word inside the node and the node itself, i get no memory leaks
or whatsoever (because according to valgrind i have more free's then
allocations)
*More* free() calls than malloc() calls indicates there is a serious
bug.
and then print them out (in-order), well, i get weird characters and
mumble jumble for insted of words. But if i dont free the word inside
the node (and get some memory leaks) then print them out it actually
works, i.e the nodes that deleted are gone and there is no weird
characters and all.
This suggests you are free()ing the same word(s) twice.

Now, you do not show the complete code for addnode(), but you
do show this:
/* is the following right ? */
memWord = malloc(sizeof(char) * strlen(token);
strcpy(memWord,token);
which is wrong -- memWord should point to strlen(token)+1 bytes,
to account for the '\0' that terminates the string. (I think
someone else pointed this out elsethread.) Of course, you should
also test the result of malloc() to see if it returned NULL, for
"out of memory". I suspect this is not the source of the observed
problem, however.

Here is your delete() function in its entirety as you posted it:
delete(char *w, TreeNode T)
{
TreeNode tmpNode;
if (T == NULL)
return T;
if (strcmp(w, T->word) < 0 )
T->left = delete(w,T->left);
else
if (strcmp(w, T->word) > 0)
T->right = delete(w,T->right);
else
{
if(T->left && T->right)
{
tmpNode = findMin(T->right);
T->word = tmpNode -> word;
T->right = delete(w,T->right);
}
else
{
tmpNode = T;
if (T->left == NULL)
T= T->right;
else if (T->right == NULL)
T= T->left;

free(tmpNode->word);
free(tmpNode);
}

}

return T;
}


Clearly something is missing and something is incorrect: the function
has a return value of type "TreeNode", which is an alias for "struct
treenode". As such it should be "TreeNode delete" or "struct
treenode delete". At the same time, however, you test T for NULL
and use "T->", which implies that T has type "pointer to struct
treenode", not "struct treenode". Perhaps the typedef named TreeNode
is an alias for "struct treenode *", and the posting-error is near
the top, rather than multiple missing "*"s in the delete() function
itself.

In any case, there is clearly a logic error as well. The delete()
function returns a pointer to the new tree so that you can keep
your tree somewhat balanced, hence the call to findMin() if there
are both left and right branches at the point you are deleting.

Now, if there are *not* two sub-trees at the point being deleted
(so that tmpNode=T and then T=T->left?T->left:T->right), you call
free() on two values: tmpNode->word and tmpNode itself. But if
there *are* two sub-trees, you find the minimum node on the right
sub-tree:

tmpNode = findMin(T->right);

While findMin() is not shown, I think we can assume that it
simply finds an appropriate node in the right-hand sub-tree
(and thus does no malloc()s and no free()s). Then you do this:

T->word = tmpNode->word;
T->right = delete(w, T->right);

The first assignment copies a pointer from tmpNode, which is some
sub-node of the right-hand tree. The second assignment calls
delete() recursively, and will free() some sub-node of the right-hand
tree *and* its word. Sine findMin() did not get "w" as a parameter,
there is no obvious strong connection between the node that findMin()
found and the node that delete() will delete -- but there is some
chance that T->word now points to the word that delete() has deleted
(i.e., the memory free()d by the call free(T->word) in the
sub-delete()); and if not, T->word points to the word in the node
findMin() found, so that two different tree nodes are sharing the
same T->word value.

In either case, this is quite wrong.

(I am not going to provide a fix, as there are lots of different
ways to fix this and you have to decide which method(s) you prefer
and why.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 15 '05 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Markus L?ffler | last post by:
Hi all, I'm looking for a class to access large memory blocks of dynamic length in an efficient way. Basically the simplest way to allocate a memory block is to allocate a byte . If you now...
2
by: Manisha | last post by:
Hi, I am creating a C++ dll which is used to process data passed to it through one of its exported functions. It should be able to process 160 simultaneous requests. For this reason, I have...
5
by: swarsa | last post by:
Hi All, I realize this is not a Palm OS development forum, however, even though my question is about a Palm C program I'm writing, I believe the topics are relevant here. This is because I...
10
by: s.subbarayan | last post by:
Dear all, I happen to come across this exciting inspiring article regarding memory leaks in this website: http://www.embedded.com/story/OEG20020222S0026 In this article the author mentions:...
4
by: learnfpga | last post by:
Here is a little code I wrote to add the numbers input by the user.....I was wondering if its possible to have the same functionality without using dynamic arrays.....just curious..... ...
3
by: odwrotnie | last post by:
Hi, is there any simple way to set components messages language? For example this, in login component: Password length minimum: 7. Non-alphanumeric characters required: 1. -- Best regards,...
7
by: Jo | last post by:
Hi, How can i differentiate between static and dynamic allocated objects? For example: void SomeFunction1() { CObject *objectp = new CObject; CObject object;
7
by: Frank | last post by:
Hi, I have the following problem with dynamic memory: int main(){ for(){ int (**w)=new int *; for(m = 0; m < N1; m++) {
4
by: duikboot | last post by:
Hello, I am trying to extract a list of strings from a text. I am looking it for hours now, googling didn't help either. Could you please help me? I expected:
1
by: Mallikarjun Melagiri | last post by:
Hi Noah, I am new to python. I'm trying to use pexpect. Following is my problem definition: I should have a script on my machine A, which should 'ssh' to machine B and from there it shud...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.