strtok & global variables

E

Estella

Hello, I wrote a function called eat_path() to split a string into
components
e.g. /a/b/c ==> namePtr[0] = a,namePtr[1] = a, namePtr[2] = c

// Global variable
char *namePtr[100] = {0};
int n; /*number of components*/

The function is like this:
void eat_path(char *pathname)
{
printf("Enter eat_path\n");
//eat_path() breaks up a pathname into component strings.
//Example : pathname = /this/is/a/test
//Then n=4, namePtr[0] ="this", namePtr[1] ="is", namePtr[2] ="a",
//namePtr[3] ="test"
//The component names will be used to search for a child under its
parent
char path[40];
char delim[] = "/"; /* delimiter is '/' */
int i = 0, j = 0;

strcpy(path, pathname);

namePtr[j++] = strtok( path, delim );

while(namePtr[j++] = strtok( NULL,delim ));

j--;

n = j;

printf("\nNumber of components: %d\n", n);

for(i = 0; i < n; i++)
{
printf("%d %s\n", i, namePtr);
}
printf("eat_path ends\n");
}

It works fine when I printed the namePtr inside this function, but
when I print namePtr in another function. it prints out garbage...

This is another function that calls eat_path:
NODE *namei(char *pathname)
{
NODE *ret;
int i = 0;

//namei() returns the node pointer of a pathname, or 0;
//First, call eat_path() to break up pathname into component strings.
printf("In namei(), pathname = %s\n", pathname);
eat_path(pathname);
printf("After eat_path: In namei(), pathname = %s\n", pathname);
for(int j = 0; j < n; j++)
printf("%d %s\n", j, namePtr[j]);
//For each component string, call search_child() to look for the
child
//under its parent.
if (pathname[0] == '/')
ret = root;
else
ret = cwd;

while (ret != 0 && i < n)
{
//printf("namePtr[%d] = %s\n", i, namePtr);
ret = search_child(ret, namePtr);
i++;
}
return ret;
}

I checked the content of namePtr right after calling eat_path, so the
namePtr should contain the same thing when the program is still inside
eat_path...
I am so lost... thank you for helping..
 
J

j

Estella said:
Hello, I wrote a function called eat_path() to split a string into
components
e.g. /a/b/c ==> namePtr[0] = a,namePtr[1] = a, namePtr[2] = c

// Global variable
char *namePtr[100] = {0};

There is no such thing as a Global variable.
While ``Global'' refers to scope, it is incorrect
to denote the variable as such. Its scope is
file-scope and its linkage is external. What
is generally referred to as ``global'' is the
appearance given when a particular
variable is used in more than one translation
unit. ``Global'' refers to scope but ``extern''
refers to linkage -- which does not affect scope,
and only when a local declaration is provided in
another translation unit may one be able to give
the appearance that the scope of a particular
variable is Global. However, the term
``Global variable'' in regards to how the abstract
machine defined by the C standard operates,
is a misnomer because it is linkage which acts
as the enabler of said appearance and not any
other mechanism.

int n; /*number of components*/

The function is like this:
void eat_path(char *pathname)
{
printf("Enter eat_path\n");
//eat_path() breaks up a pathname into component strings.
//Example : pathname = /this/is/a/test
//Then n=4, namePtr[0] ="this", namePtr[1] ="is", namePtr[2] ="a",
//namePtr[3] ="test"
//The component names will be used to search for a child under its
parent
char path[40];
char delim[] = "/"; /* delimiter is '/' */
int i = 0, j = 0;

strcpy(path, pathname);

Your problem is that the scope of ``path'' is
local to ``eat_path'' and has automatic storage
duration which means that the value it represents
is not meaningful after ``eat_path'' returns.

In function ``namei'', when you call ``eat_path''
and after ``eat_path'' returns, you rely on an object
whose value is indeterminate and upon using it
invoke undefined behaviour.
 
B

Barry Schwarz

Hello, I wrote a function called eat_path() to split a string into
components
e.g. /a/b/c ==> namePtr[0] = a,namePtr[1] = a, namePtr[2] = c

// Global variable
char *namePtr[100] = {0};
int n; /*number of components*/

The function is like this:
void eat_path(char *pathname)
{
printf("Enter eat_path\n");
//eat_path() breaks up a pathname into component strings.
//Example : pathname = /this/is/a/test
//Then n=4, namePtr[0] ="this", namePtr[1] ="is", namePtr[2] ="a",
//namePtr[3] ="test"
//The component names will be used to search for a child under its
parent
char path[40];

path exists only for the life of eat_path.
char delim[] = "/"; /* delimiter is '/' */
int i = 0, j = 0;

strcpy(path, pathname);

namePtr[j++] = strtok( path, delim );

Each non-NULL element of namePtr points to some part of path.
while(namePtr[j++] = strtok( NULL,delim ));

j--;

n = j;

printf("\nNumber of components: %d\n", n);

for(i = 0; i < n; i++)
{
printf("%d %s\n", i, namePtr);


path still exists at this point so the values in namePtr point to an
existing object.
}
printf("eat_path ends\n");
}

It works fine when I printed the namePtr inside this function, but
when I print namePtr in another function. it prints out garbage...

This is another function that calls eat_path:
NODE *namei(char *pathname)
{
NODE *ret;
int i = 0;

//namei() returns the node pointer of a pathname, or 0;
//First, call eat_path() to break up pathname into component strings.
printf("In namei(), pathname = %s\n", pathname);
eat_path(pathname);
printf("After eat_path: In namei(), pathname = %s\n", pathname);
for(int j = 0; j < n; j++)
printf("%d %s\n", j, namePtr[j]);

path no longer exists because eat_path has finished. The values in
namePtr now point to a non-existent object and any attempt to
dereference those values invokes undefined behavior.

snip


<<Remove the del for email>>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,163
Latest member
Sasha15427
Top