Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
Hello,

I am having trouble with the following code. Please direct me to the right resource, or point out where am I going wrong.

typedef struct _file
{
    TCHAR        *name;
    struct _file *parent;
} file;

void SetName(file* image)
{
    (*image).name = \\..Some string.
}

void PrintName(file* image)
{
    _tprintf(_T("Name=%s\n"), (*image).name);
}

int _tmain(int argc, _TCHAR* argv[])
{
    file fileArray[10];
    SetName(&fileArray[0]);
    PrintName(&fileArray[0]);

    return 0;
}


The problem i am having is that if i print the value of "name" in the SetName function, it prints correctly, but in the PrintName function, it gets screwed up.

Something to do with the way the structure is being passed between functions?

Any help is much appreciated.

Thanks.



So here goes the detailed problem.

The project settings are set to use UNICODE character set.


typedef struct _file
{
    wchar_t      *name;
    struct _file *parent;
} file;
void SetName(_TCHAR* dir, file* image)
{
    TCHAR filePath[MAX_PATH];
    StringCchCopy(filePath, MAX_PATH, dir);
    (*image).name = filePath;
}
void PrintName(file* image)
{
    _tprintf(_T("Name=%s\n"), (*image).name);
}
int _tmain(int argc, _TCHAR* argv[])
{
    file fileArray[10];
    SetName(argv[1], &fileArray[0]);
    PrintName(&fileArray[0]);
    return 0;
}


This code causes the problem.

After the comments, I tried a few other things which worked -
1. Assigning name to _T("blahblah") works.
2. Copying each character from filePath to name works.

Please explain the sense out of this. And also the solution to the problem.

Thanks a lot for all the comments.
Posted
Updated 8-May-11 0:59am
v2

_abhi_ wrote:
(*image).name = \\..Some string.
This is the critical line (and you didn't show us the actual code). It would work just with string literals and <code>static (or global) character arrays, in other cases you have to allocate memory for the string.
 
Share this answer
 
Just tried it in VC2008 (on WinXP SP3)

Used:

(*image).name = _T("cccvbncxvbncvbncvbncvbncvbn");


Worked fine for me.

With:

(*image).name = (TCHAR *) "cccvbncxvbncvbncvbncvbncvbn";


I get junk.
No doubt I could try other variations of your \\..Some string.
What are you using?

FYI I've done this in a C++ test app that I adapt for all sorts of things - have you tried it in C++ rather than plain C?
 
Share this answer
 
Comments
Richard MacCutchan 7-May-11 11:36am    
ASCII vs Unicode issue?
NuttingCDEF 7-May-11 11:39am    
Quite possibly - I was thinking that almost anything that confused 1/2/multibyte chars or fouled up memory allocation could be an issue - the one line of code we weren't given is quite probably where the problem lies.
_abhi_ 7-May-11 14:30pm    
I am using a TCHAR array there. And yes you guys are right I think, because when I use wchar_t array, it works fine. Can you explain this behavior?
Richard MacCutchan 7-May-11 14:44pm    
Well it sounds like you have a Unicode project and you are passing an ASCII string where a Unicode one is expected. Tidy up your project so that everything is in the correct character encoding.
NuttingCDEF 8-May-11 4:20am    
Agree - would need to see detailed code to sort out exactly what the problem is, but there is evidently an issue with character / string types - at some point it is likely that a char string is being cast to a wchar_t string which causes the problem - or maybe a confusion over number of bytes vs. number of characters causing a buffer overrun - or maybe something going wrong with preprocessor definitions / include files etc. (if there are multiple code files, are the includes / definitions consistent between them?) - or . . .

See http://www.codeproject.com/Tips/76252/What-are-TCHAR-WCHAR-LPSTR-LPWSTR-LPCTSTR-etc.aspx for a good CP article on this that might help.
This solves the problem -

struct
{
    wchar_t name[MAX_PATH];
}


and

wcsncpy_s((*image).name, filePath, MAX_PATH);
 
Share this answer
 
Comments
NuttingCDEF 8-May-11 10:03am    
I think that's pretty much what I've put in my latest solution.

The only thing I'd add is that you seem to be mixing WCHAR and TCHAR - fine so long as you are compiling everything as unicode as TCHAR and WCHAR will then be the same - but if you (or anyone who comes after you) ever changes the compilation options, you have a potential bug as TCHAR and WCHAR might then not be the same. Hopefully a smart compiler would pick it up, but sticking to one or the other (probably TCHAR ?) throughout might be preferable.
filePath is declared as an array within SetName - so allocates memory on the stack - into which you copy your string and then set .name to point to that memory.

SetName then returns - so the filePath memory is cleaned up as the stack frame unwinds (and may be reused later for other things in subsequent calls) - but .name still points to that, now invalid, memory.

So when you then call PrintName, who knows what the memory that .name points to might then contain! If it still contained your string that would be purely coincidence - unlikely because the PrintName call / stack frame itself stands a fair chance of overwriting it - and unfortunate because it would hide a nasty bug.

Remember, your .name is only a pointer to a string - your _file struct does not contain the actual string itself.
Somewhere you need to manage the memory that the string is stored in.

If you declared name using:

TCHAR name[MAX_PATH]


and then copied the string to it using

StringCchCopy((*image).name, MAX_PATH, dir)


that works - the string is now stored in the _file struct and not on the stack.
Alternatively, manage the memory for your strings elsewhere outside _file and outside SetName - and continue to use pointers.
Which route you go depends in part on things like efficient use of memory, avoiding copying strings from one place to another more often than necessary etc.

Hope this helps.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900