|
Rather than trying things at random, I suggest two things:
1.
yes you can start heuristically, i.e. guess at what the problem could be, investigate, try an alternative. But that will only solve the simple problems. if you can't find the overall solution, it could well be there is more than one problem; fixing the first may be unnoticeable as long as the others haven't been fixed. And that is exactly why debugging can be tiresome, and programming defensively pays off.
This also implies that "no, this change does not help" is irrelevant, the change may still be an essential part of the fix.
2.
but when heuristics fail, you need a systematic approach, which always start from the facts. Not the things you think hold true, as some of them obviously don't (otherwise your code would run fine). The only facts that count are those that you have observed by looking at intermediate values, either by printing them out (log statements) or by single-stepping and using debugger features.
The first anomaly you encounter must be remedied, it doesn't make much sense to ignore it and continue, it can only confuse you. So, take small steps, observe, and fix everything that is less than perfect.
BTW: with #2, your problem will be history in a couple of minutes. Add log statements (use hex, so you see all those pesky non-printable characters as well), and use the gray cells.
|
|
|
|
|
I see a number of conceptual mistakes here, and some of them might be part of the problem you perceive:
1. You are using statically defined buffers for storing a string of dynamic length. You cannot do that, since the behaviour of your function(s) will be undefined if for whatever reason the total string length exceeds the length of your buffer. Just using an arbitrary 'large' size is exactly the kind of thinking that caused the year 2000 bug histeria. The better solution is to calculate the size you need and dynamically allocate a buffer large enough for your purposes.
2. The third parameter of strncat is the maximum number of characters being appended. If you want to make sure that you don't write past the end of your buffer, you first need to calculate the length of the string currently stored within that buffer, using e. g. the strlen() function, and then calculate the difference.
However, that point is moot if you do what I stated in 1. since you will already know for sure that your buffer is sufficiently large - you made it so!
3. Beyond what I stated in 2., while you tried to avoid writing past the end of the buffer, you didn't care to check whether that actually causes a truncation of the concatenated string. Depending on what you want to do with that string, truncating it might render it unusable, and your function's behaviour becomes unpredictable.
4. Using strncat() or strncpy() instead of strcat and strcopy will truncate the terminating 0-character if the concatenated string is too long. As a result, your buffer will contain a string of undefined length, a length that will be equal or greater than your buffer size. Any followup calls to strncat() or strcat() will inevitably write past your reserved buffer. Not to mention that your buffer, when interpreted as a 0-terminated string, will be invalid for your purposes.
Summary:
(a) Do not use strncat() or strncpy! At all! The strings you are working with must not be truncated. A truncated directory name will cause errors as will truncated file names. There is no point at all in using functions that might truncate your strings without producing any indication that they did!
(b) Always use precise length for your string literals and string buffers! For string literals, just don't supply the length, define them like this instead:
char template_file_path[] = "c:\\Dragon\\Speaker\\" ;
And for dynamically sized buffers, calculate the exact length that you need:
char *temporary_file_path = new char[strlen(template_file_path)+strlen(voice_template_g)+1];
(and don't forget the delete [] temporary_file_path; later)
(or use malloc and free if you must)
(c) Use strcpy and strcat to make sure your path and filenames are not truncated, and your final string will be 0-terminated.
If you have a C++ compiler, it would of course be much easier to just use std:string instead of char* ...
|
|
|
|
|
I took your advice, and came up with this, and it works!
char* voice_template = new char [ strlen(user_voice_template_g) ] ;
char directory[] = "c:\\Dragon\\Speaker\\" ;
char* template_path = new char[ strlen( voice_template ) + strlen( directory ) + 1 ] ;
strcpy( voice_template, user_voice_template_g ) ;
strcpy( template_path, directory ) ;
strcat( template_path, voice_template ) ;
dragon_object = new Dragon_Base(dragon_voice_utility_g, template_path, NULL);
but something interesting came up in the process. I starting moving everything into my code and I put my _chdir function back in and I start getting errors again. It has everything to do with my _chdir function call. MSDN says that using _chdir changes the working directory, but I was thinking that it would stay in the C drive, so that didn't matter. So now, if I call _chdir, it craps out again. But hey, that's workable now. I got a good lesson on dynamic allocation of memory =) thanks!
char* voice_template = new char [ strlen(user_voice_template_g) ] ;
char directory[] = "c:\\Dragon\\Speaker\\" ;
char* template_path = new char[ strlen( voice_template ) + strlen( directory ) + 1 ] ;
strcpy( voice_template, user_voice_template_g ) ;
strcpy( template_path, directory ) ;
strcat( template_path, voice_template ) ;
if( !_chdir( template_path ) )
{
}
else
{
strcpy( template_path, "c:\\Dragon\\Speaker\\IPART" ) ;
}
dragon_object = new Dragon_Base(dragon_voice_utility_g, template_path, NULL);
|
|
|
|
|
Glad to be of help. There's still an error though: when you call strlen(somestring) what you get is not the actual size required to store a 0-terminated string, you only get the number of actual characters, or length of the string stored in this variable. It does not account for the terminating 0-byte. So when using strlen() for the purpose of allocating a sufficiently long block of memory, you always have to add 1! So instead of
pjdriverdude wrote:
char* voice_template = new char [ strlen(user_voice_template_g) ] ;
you should write
char* voice_template = new char [ strlen(user_voice_template_g) + 1 ] ;
You can also see this technique in the second example I gave: there I added the two strlen results and added another 1 on top of that.
That said, the missing byte might not cause any issues: using strcpy and strcat in place of strncpy and strncat makes sure the terminating 0 will be copied even if it's past the buffer. This can cause a lot of trouble if that memory location is being used for something else, but it is entirely possible for a single byte address to remain unused.
|
|
|
|
|
Hello,
Is MFC coding different for different versions of visual studio.
Pritha
modified on Monday, September 27, 2010 5:44 PM
|
|
|
|
|
Yes and no.
They occasionally change the argument/parameter order in a method (i.e. CRegKey changed between 6.0 and 2003) but for the most part, the overall approach tends to change little. Ivor Horton has hardly changed his "Beginning Visual C++" books over the years since the basics have not changed all that much.
However, I don't think I've ever been able to compile an MFC application with a newer version of Visual Studio without needing to change a few things such as the project VC++ Directories, minor shifts in the header files, etc...
ATL has changed a bit over the years and a few things have been left out in newer versions of Visual C++ so that tends to be the most painful part if you utilize any ATL.
|
|
|
|
|
|
Greetings!
I need to get the help button at the bottom left of the older version of the CPrintDialog class to point to something other than its default location.
Is there a way to do so?
I was able to hide the Help button with code resembling the following line:
dlg.m_pd.Flags -= PD_SHOWHELP;
Thank you for your help.
Regards,
Rajneesh
|
|
|
|
|
for that, you need to get get the control ID of the 'Help' button on PrintDialog. Using Spy++, i could find it as 0x40E. Don't know whether it is #defined anywhere
Try adding an MFC class (say CMyPrintDlg), derived from CPrintDialog, override its OnInitDialog().
BOOL CMyPrintDlg::OnInitDialog()
{
CPrintDialog::OnInitDialog();
CWnd *pBtnHelp = this->GetDlgItem(0x40E);
if(pBtnHelp)
{
CRect rc;
pBtnHelp->GetWindowRect(&rc);
ScreenToClient(&rc);
pBtnHelp->SetWindowPos(0, 0, rc.top, 0, 0, SWP_NOSIZE);
}
return TRUE;
}
and invoke it..
CMyPrintDlg dlg(FALSE, PD_PAGENUMS | PD_USEDEVMODECOPIES | PD_SHOWHELP);
dlg.m_pd.nMinPage = dlg.m_pd.nFromPage =1;
dlg.m_pd.nMaxPage = dlg.m_pd.nToPage = 10;
if (dlg.DoModal() == IDOK)
{
}
|
|
|
|
|
Hello Friends
How can I use Libtiff in my project.
I want to open a existing tiff image and recreate with layers while it is opened in application.and want to exchange layers with each other also.
Any Ideas?
Thanks In Advance.
Regards
Yogesh
|
|
|
|
|
There's a looooot of documentation at LibTIFF website.
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]
|
|
|
|
|
Hi all,
I have made a sdi application, in that application i have made a splitter control. On Left and right side of splitter control i have placed a class derived from CFormView. On Left side of Splitter control on form view i have placed a Report style list control. All things are working fine bu my List control is not displaying vertical scrollbar but instead it is displaying a horizontal scrollbar.
What can i do?
Can anybody help me in this?
Thanks in advance
|
|
|
|
|
Are you resizing the list control properly? Make sure the control is not wider than your splitter pane. Also, you need to populate the list with enough items to make the scroll bar visible.
If the list should fill the entire area, you could use a CListView instead.
|
|
|
|
|
if the points specified above are alright, another reason for only the horizonatal scrollbar to get showed is, setting the LVS_ALIGNLEFT property to list control. Try changing it to LVS_ALIGN_TOP.
m_listControl.ModifyStyle(0, LVS_ALIGNTOP, 0);
|
|
|
|
|
Any pointer to a good introduction to such matters ?
|
|
|
|
|
|
About bit-fields, you can start from here[^]
|
|
|
|
|
|
I created some edit controls on a dialog box at run time. How to set tab order for those controls?
|
|
|
|
|
|
I have 5 Edit ownerdraw controls on dialog. How to set Tab order in a go?
|
|
|
|
|
By default the tab order is set in the order of creation of the controls.
To change this you can use SetWindowPos by specifying the hWndInsertAfter parameter.
|
|
|
|
|
Hi All,
I need to create an intellisense type drop down which will show up when user presses a key combination inside a text editor. This drop down will contain english words pulled from a database. User can choose the word from the dropdown which he want to insert inside the text editor.
Please tell me how to create dropdown list dynmically on a key press.
I successfully hooked the key combination.
Thank You.
Regards,
John.
modified on Monday, September 27, 2010 5:45 PM
|
|
|
|
|
I have a MFC based window application developed in VC6.0. We have developed it in English language. Hence all the menu, windows, messages and other text of the application are displayed in English.
I want it to be displayed in other languages also.
Is there any quick way to do the conversion of the language?
What is the way to do the conversion?
Please suggest me with all the possible ways to convert the langugage.
Thanks in advance,
Mohan
|
|
|
|
|
This [^]should be a good place to start.
I am a HUMAN. I have that keyword (??? too much) in my name........
_AnsHUMAN_b>
|
|
|
|
|