• Welcome to Valhalla Legends Archive.
 

strange strncpy behavior

Started by Okee, December 04, 2004, 04:53 PM

Previous topic - Next topic

Okee

I've got a function I've created that include a strncpy call. Here's my function...


char* GameIndexToName(int Index)
{
char* gamename;
//strncpy(gamename, "Starcraft Retail", 16);
switch (Index)
{
case 3:
strncpy(gamename, "Starcraft Retail", 16);
return gamename;
break;
case 6:
strncpy(gamename, "Diablo II", 9);
return gamename;
break;
default:
strncpy(gamename, "Starcraft Retail", 16);
return gamename;
break;
}
return gamename;
}


This function compiles fine. When I run it, it crashes. I've narrowed it down to the strncpys by commenting them out. Does anyone see why this would cause the program to crash? Has to do with the pointer, I'm sure.

Mephisto

The pointer isn't pointing to allocated memory where strncpy can put what it's copying to.  You either need to do one of the following:

char gamename[SPACE_EQUAL_TO_THE_AMOUNT_YOU_NEED];
or...
char *gamename = new char[SPACE_EQUAL_TO_THE_AMOUNT_YOU_NEED];
// ...
delete [] gamename;

warz

#2
No, he needs to learn the basics of C++ before attempting to to mess with winapi.
Okee, from your other posts I see your dabbling with winapi at an early stage in your C++ career or whatever.

change it so that it is void functionname(char* gamename, int index)

if you have char* functionname() you will have to allocate memory, you can't return the address of something declared in the function with automatic storage class.
if you declared it inside with static storage class, that would be permissable, although bad style

I'd switch it to look like this:

void GameIndexToName(char* gamename, int Index)
{
strcpy(gamename, "Starcraft Retail");
switch (Index)
{
case 1:
strcpy(gamename, "Starcraft Retail");
break;
case 0:
strcpy(gamename, "Diablo II");
break;
default:
strcpy(gamename, "Starcraft Retail");
break;
}
}


GameIndexToName(szGameName, int iIndex);

Edit: Mephistos thing would work but I just see errors in the future if u implement that. Assertion errors or something because youd have to keep deleting gamename and stuff. *shrug*

Eibro

Nice! Someone deleted my post.
As I was saying, this situation is one where std::string comes in handy. Failing that, you could return an std::auto_ptr< char >
Eibro of Yeti Lovers.

MyndFyre

Aren't you getting compile-time warnings?  I can't recall whether or not VC has this warning, but see my comments in your code:

Quote from: Okee on December 04, 2004, 04:53 PM

switch (Index)
{
case 3:
strncpy(gamename, "Starcraft Retail", 16);
return gamename;
break; // Unreachable code detected.
case 6:
strncpy(gamename, "Diablo II", 9);
return gamename;
break; // Unreachable code detected.
default:
strncpy(gamename, "Starcraft Retail", 16);
return gamename;
break; // Unreachable code detected.
}
return gamename;


Aside from that, you need (as I believe warz pointed out) to allocate your memory and pass it in via a pointer outside of the function.  You're thinking in Java or C#.

What you COULD do is:


/// [in, out] pGameName: pointer to allocated memory.  Outputs the game name.
/// [in] Index: game index
/// [out] nSize: length of the string
BOOL GameIndexToName(IN OUT char* pGameName, IN int Index, OUT int &nSize)
{
BOOL valid = FALSE;
switch (Index)
{
case 3:
strncpy(pGameName, "Starcraft Retail", 16);
valid = TRUE;
nSize = 16;
break;
case 6:
strncpy(pGameName, "Diablo II", 9);
valid = TRUE;
nSize = 9;
break;
default:
strncpy(pGameName, "Starcraft Retail", 16);
valid = TRUE;
nSize = 16;
break;
}
return valid;
}
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Arta

I'd do it like this, although some would consider it bad style:


const char *GameIndexToName(int Index)
{
   switch(Index)
   {
       case 3: return "Starcraft Retail";
       case 6: return "Diablo II";
       default: return "Starcraft Retail";
   }
}


Of course, that comes with the caveat that you can't modify the returned string without copying it somewhere else first, but IMHO, that isn't usually an issue for something like this. I'd imagine this function being used mostly in places where that doesn't matter:


sprintf(Buffer, "You have selected product: %s\n", GameIndexToName(ProductIndex));