const char * LDevice::getMonth()
{
// LTimeMonth DOES have a value
char * LTimeMonthTMP;
printf("Test 1\n");
sprintf(LTimeMonthTMP, "%i", LTimeMonth); // --- CRASHES HERE ---
printf("Test 2\n");
CFG_SelectGroup(LTimeMonthTMP, CFG_False);
printf("Test 3\n");
return CFG_ReadText("Name", LTimeMonthTMP);
}
So, I was curious, why does it crash?
sprintf, itoa, etc...
I'm having a problem converting an integer to char or const char *. The following code gets the "Month Names" from a configuration file, but the program crashes right after the log says "Test 1", so its at the sprintf line.
Note: I also tried using itoa, but I switched to sprintf for more of a standard function, besides, they both caused crash at the same point.
You never allocate:
char * LTimeMonthTMP;
So this results in undefined behaviour:
sprintf(LTimeMonthTMP, "%i", LTimeMonth); // --- CRASHES HERE ---
/sigh
char* are evil....
hehe, thanks. Indeed, normally they say to use std::string, but I like doing things the wrong way :), thanks again.
Quote:Original post by AaronAWhy? (Just curious...)
...but I like doing things the wrong way :)
Because I operate under the theory that as long as it works like I told it to, its perfectly fine. I can think of a million and one people against that and understand why, however at this particular point and on this particular project, I feel that it shouldn't concern me. :)
Quote:Because I operate under the theory that as long as it works like I told it to, its perfectly fine.
A program always works as you tell it to. The problem is that, with char*, it's extremely easy to tell the program to crash, leak memory, or do things that you don't want it to do. In your source, the program did exactly what you asked it to: access a pointer which it didn't own. Basically, you have two options here.
- Write correct C-string code to manipulate strings. This implies measuring how much memory you must allocate for the result, allocate that memory, perform the operations in a safe manner (that is, snprintf, strncpy, strncat instead of sprintf, strcpy, strcat), and deallocate the memory (making sure that it is always deallocated when the function exits, including when an exception happens).
const char * LDevice::getMonth(){ const unsigned size = snprintf(0,0,"%i", LTimeMonth); char *strMonth = new char[size+1]; try { snprintf(strMonth,size,"%i",LTimeMonth); CFG_SelectGroup(strMonth, CFG_False); const char *found = CFG_ReadText("Name", strMonth); delete[] strMonth; return found; } catch(...) { delete[] strMonth; throw; }}
- Use modern C++, using std::string and the corresponding helper classes and functions to write shorter and safe code.
const char * LDevice::getMonth(){ std::stringstream conversion; std::string strMonth = (conversion << LTimeMonth).str(); CFG_SelectGroup( strMonth.c_str(), CFG_False ); return CFG_ReadText( "Name", strMonth.c_str() );}
There is no third way that you can follow which will result in code which does what you intend. So, do you think you can write code using method one, and do you think it's worth the additional effort?
Quote:Original post by dgreen02
Unless you know what you're doing :-D
Kinda like nitroglycerin—reason why dynamite was invented in the first place.
I can respect that, but wouldn't you feel that I reserve the right to use char * if I'd like? Even if its wrong, it'll give me a hands on learning lesson as they say :). I've already used quite a few char *'s anyway so switching now doesn't sound like my cup of tea, sorry, I'll try to include a warning if I decide to publicize the game :P.
At this point yes (because I don't need conversion often). How about when I decide to start a new project, I'll use string instead? But right now it isn't fitting on the agenda.
Quote:So, do you think you can write code using method one, and do you think it's worth the additional effort?
At this point yes (because I don't need conversion often). How about when I decide to start a new project, I'll use string instead? But right now it isn't fitting on the agenda.
I personally try to avoid sprintf, etc:
or, avoiding char* like the plague...
(Oops, beaten to the punch by ToohrVyk)
int integer = 50;ostringstream oss;oss << integer;char *ca = new char[oss.str().length() + 1];// or memcpy, or copy...for(size_t i = 0; i < oss.str().length(); i++) ca = oss.str();ca[oss.str().length()] = '\0';...delete [] ca;
or, avoiding char* like the plague...
ostringstream oss;oss << integer;string s = oss.str();
(Oops, beaten to the punch by ToohrVyk)
On second thought, the direct usage of new/delete can (should?) be avoided for arrays:
int i = 50;ostringstream oss;oss << i;string s = oss.str();vector<char> vc(s.begin(), s.end());vc.push_back('\0');// Equivalent to char* only for vector container.cout << &vc[0] << endl;// The vector class automatically deletes its contained memory when the deconstructor is called.// No potential memory leaks.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement