Problem with Array of char*
-
Ok look, here is the full function (that I did NOT write myself) which should work correct, but I think >>I<< do something NOT correct. Its a tokenizer for char-strings
int strtoken(char *str, char *separator, char *token[])
{
int i = 0;token\[0\] = strtok(str, separator); //This line crashes while ( token\[i\] ) { i++; token\[i\] = strtok(NULL, separator); } return ( i ); }
And I call it that way atm:
char \*token\[256\]; //I think that is an array of char\*, isn't it? for(int i = 0; i < 256; i++) { token\[i\] = '\\0'; } Helper::instance()->strtoken(name, ".", token);
name is a char* e.g. "system.fullscreen"
OK, as already suggested by «_Superman_», probably your code is crashing because you're passing a string literal to the function (
strtok
cannot access for writing a constant string). for instancechar * name = "system.fullscreen";
token[0] = strtok(name, "."); // exception herewould crash the application, while
char name[] = "system.fullscreen";
token[0] = strtok(name, ".");should work fine. :)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
Ok look, here is the full function (that I did NOT write myself) which should work correct, but I think >>I<< do something NOT correct. Its a tokenizer for char-strings
int strtoken(char *str, char *separator, char *token[])
{
int i = 0;token\[0\] = strtok(str, separator); //This line crashes while ( token\[i\] ) { i++; token\[i\] = strtok(NULL, separator); } return ( i ); }
And I call it that way atm:
char \*token\[256\]; //I think that is an array of char\*, isn't it? for(int i = 0; i < 256; i++) { token\[i\] = '\\0'; } Helper::instance()->strtoken(name, ".", token);
name is a char* e.g. "system.fullscreen"
-
OK, as already suggested by «_Superman_», probably your code is crashing because you're passing a string literal to the function (
strtok
cannot access for writing a constant string). for instancechar * name = "system.fullscreen";
token[0] = strtok(name, "."); // exception herewould crash the application, while
char name[] = "system.fullscreen";
token[0] = strtok(name, ".");should work fine. :)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles]Your right, I get a char* name as a parameter and use it to call the function. Thats the cause of the crash. But how do I solve this problem? I have this char *name and it has to be tokenized. How can I do that as strtok crashes with it? Btw. thanks for your help, I would have never thought of THAT ^^
-
Your right, I get a char* name as a parameter and use it to call the function. Thats the cause of the crash. But how do I solve this problem? I have this char *name and it has to be tokenized. How can I do that as strtok crashes with it? Btw. thanks for your help, I would have never thought of THAT ^^
well, if you really need to use that fucntion, then you may assign the array the way I shown in my previous post, or do someting like:
char * name;
name = _strdup("system.fullscreen");
if ( name )
{
strtoken(name, ".", token);
free(name); // don't forget to free memory
}:)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
well, if you really need to use that fucntion, then you may assign the array the way I shown in my previous post, or do someting like:
char * name;
name = _strdup("system.fullscreen");
if ( name )
{
strtoken(name, ".", token);
free(name); // don't forget to free memory
}:)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles]But if I call it with that char* it crashes! I have a function
doSomething(char *name)
{
[...]
strtoken(name, ".", token); //crashes
}That works but it does not help me:
doSomething(char *name)
{
[...]
char foo[] = "hello.world";
strtoken(foo, ".", token); //does NOT crash
}But how can I use strtoken with char *name? Can I make a char foo[] out of char *name?
-
But if I call it with that char* it crashes! I have a function
doSomething(char *name)
{
[...]
strtoken(name, ".", token); //crashes
}That works but it does not help me:
doSomething(char *name)
{
[...]
char foo[] = "hello.world";
strtoken(foo, ".", token); //does NOT crash
}But how can I use strtoken with char *name? Can I make a char foo[] out of char *name?
if you really need to pass a constant string to
doSomething
, the you may write (as already suggested)doSomething(char * name)
{
//...
char * name_writable_copy = _strdup( name );
if ( name_writable_copy )
{
strtoken(name_writable_copy, ".", token);
free( name_writable_copy );
}
else
{
// handle (unusual) allocation error
}
}The above code shouldn't crash. :)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
if you really need to pass a constant string to
doSomething
, the you may write (as already suggested)doSomething(char * name)
{
//...
char * name_writable_copy = _strdup( name );
if ( name_writable_copy )
{
strtoken(name_writable_copy, ".", token);
free( name_writable_copy );
}
else
{
// handle (unusual) allocation error
}
}The above code shouldn't crash. :)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
Well, good luck! :)
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
Ok look, here is the full function (that I did NOT write myself) which should work correct, but I think >>I<< do something NOT correct. Its a tokenizer for char-strings
int strtoken(char *str, char *separator, char *token[])
{
int i = 0;token\[0\] = strtok(str, separator); //This line crashes while ( token\[i\] ) { i++; token\[i\] = strtok(NULL, separator); } return ( i ); }
And I call it that way atm:
char \*token\[256\]; //I think that is an array of char\*, isn't it? for(int i = 0; i < 256; i++) { token\[i\] = '\\0'; } Helper::instance()->strtoken(name, ".", token);
name is a char* e.g. "system.fullscreen"
error1408 wrote:
Helper::instance()->strtoken(name, ".", token);
How about something like:
char *temp = new char[strlen(name) + 1];
strcpy(temp, name);
Helper::instance()->strtoken(temp, ".", token);"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
-
error1408 wrote:
Helper::instance()->strtoken(name, ".", token);
How about something like:
char *temp = new char[strlen(name) + 1];
strcpy(temp, name);
Helper::instance()->strtoken(temp, ".", token);"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
DavidCrow wrote:
How about something like: char *temp = new char[strlen(name) + 1]; strcpy(temp, name); Helper::instance()->strtoken(temp, ".", token);
Ok this works! But I don't understand why...could someone explain it to me? Why does the param char * not work but the char * thats created here? Btw. I have to DELETE the char *temp afterwards, right?
-
DavidCrow wrote:
How about something like: char *temp = new char[strlen(name) + 1]; strcpy(temp, name); Helper::instance()->strtoken(temp, ".", token);
Ok this works! But I don't understand why...could someone explain it to me? Why does the param char * not work but the char * thats created here? Btw. I have to DELETE the char *temp afterwards, right?
error1408 wrote:
Why does the param char * not work but the char * thats created here?
Work through this:
void main( void )
{
char *abc = "First";
char xyz[] = "Last";abc\[0\] = '1'; xyz\[0\] = '2';
}
error1408 wrote:
Btw. I have to DELETE the char *temp afterwards, right?
Correct (since it points to heap memory).
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
-
error1408 wrote:
Why does the param char * not work but the char * thats created here?
Work through this:
void main( void )
{
char *abc = "First";
char xyz[] = "Last";abc\[0\] = '1'; xyz\[0\] = '2';
}
error1408 wrote:
Btw. I have to DELETE the char *temp afterwards, right?
Correct (since it points to heap memory).
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
-
Ok I think I got it. So is it right, that in my case I can not know if the char *name that I get is a literal or not so to be sure it's not I have to create a temp array?
error1408 wrote:
...I can not know if the char *name that I get is a literal or not so to be sure it's not I have to create a temp array?
You'll notice in my example that both variables pointed to a string literal, yet only one of them could be changed. Therein lies the difference between a
char*
vs.char[]
. See here for more."Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
-
Ok I think I got it. So is it right, that in my case I can not know if the char *name that I get is a literal or not so to be sure it's not I have to create a temp array?
i agree with the pallini's solution and also david gave a good description. string literals r located in a const part of memory which is not writable. this is why arrays don't cause crash. they're located in heap or stack based on whether u allocate them or use local variables which r both writable parts of memory. there's an API function to determine whether a block of memory or a string is const named AfxIsValidAddress. it may also test whether the block is writable. but if i were u, i would use _strdup anyway, and would pass the arg as const for the caller to make sure that the original version of the passed string is not altered.