vc++ - strtok() access violation

N

nobody

Hi:

I am using Visual Studio .NET 2003 and console project (disabled
precompiled header).

I am using _tcstok() which resolves to strtok in my case. It keeps
crashing (unhandled error, access violation). Firt I thought my variable
wasn't writtable (const) but it wasn't so I used literal as input but it
still crashes.

it crashes exactly in strtok.c (line 99):

....

for ( ; *str ; str++ )
if ( map[*str >> 3] & (1 << (*str & 7)) ) {
*str++ = '\0';
break;
}

....


My test call is like this strtok("hklm\\software","\\"); Anyhow I went
through all over the net and I didn't find anything related to my problem.

Thanks in advance.
 
M

Mike Wahler

nobody said:
Hi:

I am using Visual Studio .NET 2003 and console project (disabled
precompiled header).

I am using _tcstok() which resolves to strtok in my case. It keeps
crashing (unhandled error, access violation). Firt I thought my variable
wasn't writtable (const) but it wasn't so I used literal as input but it
still crashes.

That's because attempting to modify a literal produces
undefined behavior (it seems in your case, this is manifest
as a 'crash').
it crashes exactly in strtok.c (line 99):

...

for ( ; *str ; str++ )
if ( map[*str >> 3] & (1 << (*str & 7)) ) {
*str++ = '\0';
break;
}

...


My test call is like this strtok("hklm\\software","\\"); Anyhow I went
through all over the net and I didn't find anything related to my problem.

Try some C++ books. See www.accu.org for peer reviews.

Change your literal to an array:

char arr[] = "hklm\\software";
strtok(arr,"\\");

And be sure to check 'strtok()'s return value to
see if it actually found anything.

-Mike
 
N

nobody

Now I feel dumb and it works like a charm.

The thing that doesn't make sense is that I made a function calling
strtok() initially. ex:

getField("hkml\\software","\\");

then getField calls strtok(), so literal passed through another variable
doesn't make that variable modifiable (ie: strtok can't modify it)?

Thanks alot.
 
D

Default User

nobody said:
Now I feel dumb and it works like a charm.

The thing that doesn't make sense is that I made a function calling
strtok() initially. ex:

getField("hkml\\software","\\");

then getField calls strtok(), so literal passed through another
variable doesn't make that variable modifiable (ie: strtok can't
modify it)?


Arrays that are passed to functions are not copied. Instead, the array
name is converted to a pointer to the first element. It is undefined
behavior to modify a string literal, such as when strtok() punches
holes in the string as it works down through it.

You'd be much better off with std::string and using one of the various
techniques for doing something similar to strtok() that yield a vector
of strings. Some have been posted here in the past.



Brian
 
N

nobody

Arrays that are passed to functions are not copied. Instead, the array
name is converted to a pointer to the first element. It is undefined
behavior to modify a string literal, such as when strtok() punches
holes in the string as it works down through it.

You'd be much better off with std::string and using one of the various
techniques for doing something similar to strtok() that yield a vector
of strings. Some have been posted here in the past.



Brian


Since the first reply I moved away from strtok because it's easier to
just do the samething myself (hard to believe myself:)).

Can someone tell me if my code is optimized and what could I do better
(areas of improvement)? In my code I let the caller release the memory
(someone said that's the COM way). Is it better to use a CONST for the
first argument?

//return left side of the delimiter
TCHAR* _tleft(TCHAR* lpszString, CONST TCHAR* chDelimiter)
{
BYTE byteSize = _tcsclen(lpszString) + 1;
TCHAR *lpszCurPos;

lpszCurPos = lpszString;

TCHAR *lpszFound = 0;

TCHAR *lpszOut = new TCHAR[byteSize];
TCHAR *lpszOut2;

lpszOut2 = lpszOut; //hold final string

lpszFound = _tcsstr(lpszString,chDelimiter);

while ((*lpszCurPos)&&((lpszFound - lpszCurPos) != 0))
{
*lpszOut++ = (TCHAR)*lpszCurPos++;
}

*lpszOut='\0';
return lpszOut2;
}

//return right side of the delimiter
TCHAR* _tright(TCHAR* lpszString, CONST TCHAR* chDelimiter)
{
BYTE byteSize = _tcsclen(lpszString) + 1;
TCHAR *lpszCurPos;

lpszCurPos = lpszString;

TCHAR *lpszFound = 0;

TCHAR *lpszOut = new TCHAR[byteSize];
TCHAR *lpszOut2;

lpszOut2 = lpszOut; //hold final string

lpszFound = _tcsstr(lpszString,chDelimiter);
if(lpszFound)
{
while ((*lpszCurPos++)&&((lpszFound - lpszCurPos) != 0))
{}
while(*lpszCurPos++)
{
*lpszOut++ = (TCHAR)*lpszCurPos;
}
*lpszOut='\0';
return lpszOut2;
}
else
return NULL;
}
 
D

Default User

Since the first reply I moved away from strtok because it's easier to
just do the samething myself (hard to believe myself:)).
Ok.

Can someone tell me if my code is optimized and what could I do
better (areas of improvement)? In my code I let the caller release
the memory (someone said that's the COM way). Is it better to use a
CONST for the first argument?

Do you have a particular reason for using all those proprietary data
types rather than the standard ones?
//return left side of the delimiter
TCHAR* _tleft(TCHAR* lpszString, CONST TCHAR* chDelimiter)
{
BYTE byteSize = _tcsclen(lpszString) + 1;

I won't even bother trying to decipher the code with all this stuff. Go
to a Microsoft newsgroup and have them look at it. If you want to do it
using nice portable standard constructs, then we'll talk again.

On the whole it looks longer and more convoluted than need be.


Brian
 

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,769
Messages
2,569,582
Members
45,061
Latest member
KetonaraKeto

Latest Threads

Top